Skip to content

Commit

Permalink
Merge pull request #100 from niltonpimentel02/dev
Browse files Browse the repository at this point in the history
feat: add pre-commit and update readme
  • Loading branch information
bbelderbos authored Oct 29, 2024
2 parents 8326e71 + 8400ee4 commit 21d0931
Show file tree
Hide file tree
Showing 43 changed files with 755 additions and 681 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -157,4 +157,4 @@ cython_debug/
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
.idea/
19 changes: 19 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: check-json
- id: check-yaml
- id: debug-statements
- id: detect-private-key
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.6.9
hooks:
# Run the linter.
- id: ruff
types_or: [ python, pyi ]
args: [ --fix ]
# Run the formatter.
- id: ruff-format
types_or: [ python, pyi ]
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,28 @@ Our simple yet effective reading tracking app: [PyBites Books](https://pybitesbo

## Setup

![](https://img.shields.io/badge/Python-3.9.0-blue.svg)
![](https://img.shields.io/badge/Django-4.1.13-blue.svg)
[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://github.com/pre-commit/pre-commit)

1. Create a [virtual env](https://pybit.es/the-beauty-of-virtualenv.html) and activate it (`source venv/bin/activate`)
2. Install the dependencies: `pip install -r requirements.txt`
3. Create a database, e.g. `pybites_books` and define the full DB URL for the next step, e.g. `DATABASE_URL=postgres://postgres:[email protected]:5432/pybites_books`.
4. Set this env variable together with `SECRET_KEY` in a file called `.env` in the root of the project: `cp .env-template .env && vi .env`. That's the bare minimum. If you want to have email working create a [Sendgrid](https://sendgrid.com/) account obtaining an API key. Same for Slack integration, this requires a `SLACK_VERIFICATION_TOKEN`. The other variables have sensible defaults.
5. Sync the DB: `python manage.py migrate`.
6. And finally run the app server: `python manage.py runserver`.

## Run pre-commit

Install the git hook scripts
```bash
pre-commit install
```
Run against all the files:
```bash
pre-commit run --all-files
```

## Local Via docker-compose

You can use docker / docker compose to run both the postgresql database as well as the app itself. This makes local testing a lot easier, and allows you to worry less about environmental details.
Expand Down
2 changes: 1 addition & 1 deletion api/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@


class ApiConfig(AppConfig):
name = 'api'
name = "api"
16 changes: 8 additions & 8 deletions api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

from . import views

app_name = 'api'
app_name = "api"
urlpatterns = [
path('users', views.user_books, name='user_books'),
path('users/<str:username>', views.user_books, name='user_books'),
path('random', views.random_book, name='random_book'),
path('random/<str:grep>', views.random_book, name='random_book'),
path('books/<str:bookid>', views.get_bookid, name='get_bookid'),
path('lists/<str:name>', views.get_book_list, name='get_book_list'),
path('stats/<str:username>', views.get_book_stats, name='get_book_stats'),
path("users", views.user_books, name="user_books"),
path("users/<str:username>", views.user_books, name="user_books"),
path("random", views.random_book, name="random_book"),
path("random/<str:grep>", views.random_book, name="random_book"),
path("books/<str:bookid>", views.get_bookid, name="get_bookid"),
path("lists/<str:name>", views.get_book_list, name="get_book_list"),
path("stats/<str:username>", views.get_book_stats, name="get_book_stats"),
]
147 changes: 77 additions & 70 deletions api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

def get_users():
user_books = defaultdict(list)
books = UserBook.objects.select_related('user').all()
books = UserBook.objects.select_related("user").all()
for book in books:
user_books[book.user.username].append(book)
return user_books
Expand All @@ -20,60 +20,63 @@ def get_users():
def get_user_last_book(username):
user = get_object_or_404(User, username=username)

books = UserBook.objects.select_related('book')
books = books.filter(user=user).order_by('-inserted')
books = UserBook.objects.select_related("book")
books = books.filter(user=user).order_by("-inserted")
if not books:
raise Http404

book = books[0]
data = dict(bookid=book.book.bookid,
title=book.book.title,
url=book.book.url,
authors=book.book.authors,
published=book.book.published,
isbn=book.book.isbn,
pages=book.book.pages,
language=book.book.language,
description=book.book.description,
imagesize=book.book.imagesize)
data = dict(
bookid=book.book.bookid,
title=book.book.title,
url=book.book.url,
authors=book.book.authors,
published=book.book.published,
isbn=book.book.isbn,
pages=book.book.pages,
language=book.book.language,
description=book.book.description,
imagesize=book.book.imagesize,
)
return data


def get_user_books(username):
data = defaultdict(list)
user = get_object_or_404(User, username=username)
books = UserBook.objects.select_related('book').filter(user=user)
books = UserBook.objects.select_related("book").filter(user=user)

for book in books:
row = dict(bookid=book.book.bookid,
title=book.book.title,
url=book.book.url,
authors=book.book.authors,
favorite=book.favorite,
published=book.book.published,
isbn=book.book.isbn,
pages=book.book.pages,
language=book.book.language,
description=book.book.description,
imagesize=book.book.imagesize)
row = dict(
bookid=book.book.bookid,
title=book.book.title,
url=book.book.url,
authors=book.book.authors,
favorite=book.favorite,
published=book.book.published,
isbn=book.book.isbn,
pages=book.book.pages,
language=book.book.language,
description=book.book.description,
imagesize=book.book.imagesize,
)
data[book.status].append(row)
return data


def user_books(request, username=None):

if username is None:
data = get_users()
else:
data = get_user_books(username)

json_data = json.dumps(data, indent=4, default=str, sort_keys=False)

return HttpResponse(json_data, content_type='application/json')
return HttpResponse(json_data, content_type="application/json")


def get_random_book(grep=None):
books = UserBook.objects.select_related('book').all()
books = UserBook.objects.select_related("book").all()

if grep is not None:
books = books.filter(book__title__icontains=grep.lower())
Expand All @@ -84,16 +87,18 @@ def get_random_book(grep=None):
count = books.count()
book = books[randint(0, count - 1)]

data = dict(bookid=book.book.bookid,
title=book.book.title,
url=book.book.url,
authors=book.book.authors,
published=book.book.published,
isbn=book.book.isbn,
pages=book.book.pages,
language=book.book.language,
description=book.book.description,
imagesize=book.book.imagesize)
data = dict(
bookid=book.book.bookid,
title=book.book.title,
url=book.book.url,
authors=book.book.authors,
published=book.book.published,
isbn=book.book.isbn,
pages=book.book.pages,
language=book.book.language,
description=book.book.description,
imagesize=book.book.imagesize,
)

return data

Expand All @@ -104,7 +109,7 @@ def random_book(request, grep=None):

json_data = json.dumps(data, indent=4, default=str, sort_keys=False)

return HttpResponse(json_data, content_type='application/json')
return HttpResponse(json_data, content_type="application/json")


def get_bookid(request, bookid):
Expand All @@ -113,29 +118,31 @@ def get_bookid(request, bookid):
raise Http404

book = books[0]
data = dict(bookid=book.bookid,
title=book.title,
url=book.url,
authors=book.authors,
publisher=book.publisher,
published=book.published,
isbn=book.isbn,
pages=book.pages,
language=book.language,
description=book.description,
imagesize=book.imagesize)
data = dict(
bookid=book.bookid,
title=book.title,
url=book.url,
authors=book.authors,
publisher=book.publisher,
published=book.published,
isbn=book.isbn,
pages=book.pages,
language=book.language,
description=book.description,
imagesize=book.imagesize,
)

json_data = json.dumps(data, indent=4, default=str, sort_keys=False)

return HttpResponse(json_data, content_type='application/json')
return HttpResponse(json_data, content_type="application/json")


def get_book_list(request, name):
books = UserBook.objects.select_related(
"book"
).filter(
booklists__name=name
).order_by("book__title")
books = (
UserBook.objects.select_related("book")
.filter(booklists__name=name)
.order_by("book__title")
)

if not books:
raise Http404
Expand All @@ -148,30 +155,30 @@ def get_book_list(request, name):
url=book.book.url,
authors=book.book.authors,
pages=book.book.pages,
description=book.book.description)
description=book.book.description,
)
data.append(book_obj)

return HttpResponse(
json.dumps(
data, indent=4, default=str, sort_keys=False),
content_type='application/json'
json.dumps(data, indent=4, default=str, sort_keys=False),
content_type="application/json",
)


def get_book_stats(request, username):
user_books = UserBook.objects.select_related(
'book'
).filter(user__username=username)
user_books = UserBook.objects.select_related("book").filter(user__username=username)

data = []
for user_book in user_books:
row = dict(bookid=user_book.book.bookid,
title=user_book.book.title,
url=user_book.book.url,
status=user_book.status,
favorite=user_book.favorite,
completed=user_book.completed)
row = dict(
bookid=user_book.book.bookid,
title=user_book.book.title,
url=user_book.book.url,
status=user_book.status,
favorite=user_book.favorite,
completed=user_book.completed,
)
data.append(row)

json_data = json.dumps(data, indent=4, default=str, sort_keys=False)
return HttpResponse(json_data, content_type='application/json')
return HttpResponse(json_data, content_type="application/json")
35 changes: 27 additions & 8 deletions books/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,16 @@
from django.contrib import admin
from django.utils.safestring import mark_safe

from .models import (Category, Book, Search, UserBook,
BookNote, Badge, BookConversion,
ImportedBook)
from .models import (
Category,
Book,
Search,
UserBook,
BookNote,
Badge,
BookConversion,
ImportedBook,
)


class CategoryAdmin(admin.ModelAdmin):
Expand All @@ -23,7 +30,11 @@ class SearchAdmin(admin.ModelAdmin):

class UserBookAdmin(admin.ModelAdmin):
list_display = ("user", "book", "status", "favorite", "completed", "inserted")
search_fields = ("user__username", "book__title", "book__bookid",)
search_fields = (
"user__username",
"book__title",
"book__bookid",
)
list_filter = ("status", "favorite")


Expand All @@ -39,7 +50,8 @@ def short_desc(self, obj):
return f"{obj.description[:limit]} ..."
else:
return obj.description
short_desc.short_description = 'short description'

short_desc.short_description = "short description"


class BadgeAdmin(admin.ModelAdmin):
Expand All @@ -55,12 +67,19 @@ def book_link(self, obj):
f"<a href='{settings.DOMAIN}/books/{obj.googlebooks_id}' "
f"target='_blank'>{obj.googlebooks_id}</a>"
)
book_link.short_description = 'Google / PyBites book link'

book_link.short_description = "Google / PyBites book link"


class ImportedBookAdmin(admin.ModelAdmin):
list_display = ("title", "book", "reading_status", "date_completed",
"book_status", "user")
list_display = (
"title",
"book",
"reading_status",
"date_completed",
"book_status",
"user",
)
search_fields = ("title",)


Expand Down
2 changes: 1 addition & 1 deletion books/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@


class BooksConfig(AppConfig):
name = 'books'
name = "books"
Loading

0 comments on commit 21d0931

Please sign in to comment.