add django-upgrade pre-commit hook and apply fixes

This commit is contained in:
FuzzyGrim
2026-02-25 23:37:58 +01:00
parent 4cd6e054a6
commit d1eed9526c
13 changed files with 65 additions and 73 deletions

View File

@@ -7,6 +7,11 @@ repos:
language: system
pass_filenames: false
always_run: true
- id: django-upgrade
name: django-upgrade
entry: django-upgrade
language: system
types: [python]
- id: ruff
name: ruff
entry: ruff check --fix

View File

@@ -1,4 +1,5 @@
coverage==7.13.3
django-upgrade==1.30.0
djlint==1.36.4
fakeredis==2.33.0
pre-commit==4.5.1

View File

@@ -11,6 +11,7 @@ from app.models import (
# Custom ModelAdmin classes with search functionality
@admin.register(Item)
class ItemAdmin(admin.ModelAdmin):
"""Custom admin for Item model with search and filter options."""
@@ -26,6 +27,7 @@ class ItemAdmin(admin.ModelAdmin):
list_filter = ["media_type", "source"]
@admin.register(Episode)
class EpisodeAdmin(admin.ModelAdmin):
"""Custom admin for Episode model with search and filter options."""
@@ -42,8 +44,6 @@ class MediaAdmin(admin.ModelAdmin):
# Register models with custom admin classes
admin.site.register(Item, ItemAdmin)
admin.site.register(Episode, EpisodeAdmin)
# Auto-register remaining models

View File

@@ -70,11 +70,11 @@ class Item(CalendarTriggerMixin, models.Model):
media_id = models.CharField(max_length=20)
source = models.CharField(
max_length=20,
choices=Sources.choices,
choices=Sources,
)
media_type = models.CharField(
max_length=10,
choices=MediaTypes.choices,
choices=MediaTypes,
default=MediaTypes.MOVIE.value,
)
title = models.TextField()
@@ -806,7 +806,7 @@ class Media(models.Model):
progressed_at = MonitorField(monitor="progress")
status = models.CharField(
max_length=20,
choices=Status.choices,
choices=Status,
default=Status.COMPLETED.value,
)
start_date = models.DateTimeField(null=True, blank=True)

View File

@@ -145,10 +145,8 @@ class HomeViewTests(TestCase):
)
# Now test the load more functionality
headers = {"HTTP_HX_REQUEST": "true"}
response = self.client.get(
reverse("home") + "?load_media_type=season",
**headers,
reverse("home") + "?load_media_type=season", headers={"hx-request": "true"}
)
self.assertEqual(response.status_code, 200)

View File

@@ -87,18 +87,16 @@ class MediaListViewTests(TestCase):
def test_media_list_htmx_request(self):
"""Test the media list view with HTMX request."""
headers = {"HTTP_HX_REQUEST": "true"}
response = self.client.get(
reverse("medialist", args=[MediaTypes.MOVIE.value]) + "?layout=grid",
**headers,
headers={"hx-request": "true"},
)
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, "app/components/media_grid_items.html")
response = self.client.get(
reverse("medialist", args=[MediaTypes.MOVIE.value]) + "?layout=table",
**headers,
headers={"hx-request": "true"},
)
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, "app/components/media_table_items.html")

View File

@@ -4,6 +4,7 @@ from django.utils import timezone
from events.models import Event
@admin.register(Event)
class EventAdmin(admin.ModelAdmin):
"""Admin configuration for the Event model."""
@@ -27,6 +28,3 @@ class EventAdmin(admin.ModelAdmin):
return timezone.localtime(obj.datetime).strftime("%Y-%m-%d %H:%M")
except (OverflowError, ValueError):
return "Invalid date"
admin.site.register(Event, EventAdmin)

View File

@@ -3,6 +3,7 @@ from django.contrib import admin
from lists.models import CustomList, CustomListItem
@admin.register(CustomList)
class CustomListAdmin(admin.ModelAdmin):
"""Admin configuration for CustomList model."""
@@ -13,20 +14,19 @@ class CustomListAdmin(admin.ModelAdmin):
autocomplete_fields = ["collaborators"]
filter_horizontal = ["collaborators"]
@admin.display(description="Number of items")
def item_count(self, obj):
"""Return the number of items in the list."""
return obj.items.count()
item_count.short_description = "Number of items"
@admin.display(description="Last updated")
def get_last_update(self, obj):
"""Return the date of the last item added."""
last_update = CustomListItem.objects.get_last_added_date(obj)
return last_update or "-"
get_last_update.short_description = "Last updated"
@admin.register(CustomListItem)
class CustomListItemAdmin(admin.ModelAdmin):
"""Admin configuration for CustomListItem model."""
@@ -37,12 +37,7 @@ class CustomListItemAdmin(admin.ModelAdmin):
autocomplete_fields = ["item", "custom_list"]
readonly_fields = ["date_added"]
@admin.display(description="Media Type")
def get_media_type(self, obj):
"""Return the media type of the item."""
return obj.item.get_media_type_display()
get_media_type.short_description = "Media Type"
admin.site.register(CustomList, CustomListAdmin)
admin.site.register(CustomListItem, CustomListItemAdmin)

View File

@@ -136,10 +136,7 @@ class ListsViewTests(TestCase):
self.client.login(**self.credentials)
# Make an HTMX request
response = self.client.get(
reverse("lists"),
HTTP_HX_REQUEST="true",
)
response = self.client.get(reverse("lists"), headers={"hx-request": "true"})
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, "lists/components/list_grid.html")
@@ -496,7 +493,7 @@ class ListDetailViewTests(TestCase):
# Make an HTMX request
response = self.client.get(
reverse("list_detail", args=[self.custom_list.id]),
HTTP_HX_REQUEST="true",
headers={"hx-request": "true"},
)
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, "lists/components/media_grid.html")

View File

@@ -17,6 +17,7 @@ class CustomUserCreationForm(UserCreationForm):
fields = ("username",)
@admin.register(User)
class CustomUserAdmin(UserAdmin):
"""Custom admin interface for the User model."""
@@ -66,5 +67,4 @@ class CustomUserAdmin(UserAdmin):
ordering = ("username",)
admin.site.register(User, CustomUserAdmin)
admin.site.unregister(Group)

View File

@@ -14,7 +14,7 @@ def get_client_ip(request):
Used when logging for user registration and login.
"""
# get the user's IP address
ip_address = request.META.get("HTTP_X_FORWARDED_FOR")
ip_address = request.headers.get("x-forwarded-for")
# if the IP address is not available in HTTP_X_FORWARDED_FOR
if not ip_address:

View File

@@ -120,7 +120,7 @@ class User(AbstractUser):
home_sort = models.CharField(
max_length=20,
default=HomeSortChoices.UPCOMING,
choices=HomeSortChoices.choices,
choices=HomeSortChoices,
)
# Media type preferences: TV Shows
@@ -128,17 +128,17 @@ class User(AbstractUser):
tv_layout = models.CharField(
max_length=20,
default=LayoutChoices.GRID,
choices=LayoutChoices.choices,
choices=LayoutChoices,
)
tv_sort = models.CharField(
max_length=20,
default=MediaSortChoices.SCORE,
choices=MediaSortChoices.choices,
choices=MediaSortChoices,
)
tv_status = models.CharField(
max_length=20,
default=MediaStatusChoices.ALL,
choices=MediaStatusChoices.choices,
choices=MediaStatusChoices,
)
# Media type preferences: TV Seasons
@@ -146,17 +146,17 @@ class User(AbstractUser):
season_layout = models.CharField(
max_length=20,
default=LayoutChoices.GRID,
choices=LayoutChoices.choices,
choices=LayoutChoices,
)
season_sort = models.CharField(
max_length=20,
default=MediaSortChoices.SCORE,
choices=MediaSortChoices.choices,
choices=MediaSortChoices,
)
season_status = models.CharField(
max_length=20,
default=MediaStatusChoices.ALL,
choices=MediaStatusChoices.choices,
choices=MediaStatusChoices,
)
# Media type preferences: Movies
@@ -164,17 +164,17 @@ class User(AbstractUser):
movie_layout = models.CharField(
max_length=20,
default=LayoutChoices.GRID,
choices=LayoutChoices.choices,
choices=LayoutChoices,
)
movie_sort = models.CharField(
max_length=20,
default=MediaSortChoices.SCORE,
choices=MediaSortChoices.choices,
choices=MediaSortChoices,
)
movie_status = models.CharField(
max_length=20,
default=MediaStatusChoices.ALL,
choices=MediaStatusChoices.choices,
choices=MediaStatusChoices,
)
# Media type preferences: Anime
@@ -182,17 +182,17 @@ class User(AbstractUser):
anime_layout = models.CharField(
max_length=20,
default=LayoutChoices.TABLE,
choices=LayoutChoices.choices,
choices=LayoutChoices,
)
anime_sort = models.CharField(
max_length=20,
default=MediaSortChoices.SCORE,
choices=MediaSortChoices.choices,
choices=MediaSortChoices,
)
anime_status = models.CharField(
max_length=20,
default=MediaStatusChoices.ALL,
choices=MediaStatusChoices.choices,
choices=MediaStatusChoices,
)
# Media type preferences: Manga
@@ -200,17 +200,17 @@ class User(AbstractUser):
manga_layout = models.CharField(
max_length=20,
default=LayoutChoices.TABLE,
choices=LayoutChoices.choices,
choices=LayoutChoices,
)
manga_sort = models.CharField(
max_length=20,
default=MediaSortChoices.SCORE,
choices=MediaSortChoices.choices,
choices=MediaSortChoices,
)
manga_status = models.CharField(
max_length=20,
default=MediaStatusChoices.ALL,
choices=MediaStatusChoices.choices,
choices=MediaStatusChoices,
)
# Media type preferences: Games
@@ -218,17 +218,17 @@ class User(AbstractUser):
game_layout = models.CharField(
max_length=20,
default=LayoutChoices.GRID,
choices=LayoutChoices.choices,
choices=LayoutChoices,
)
game_sort = models.CharField(
max_length=20,
default=MediaSortChoices.SCORE,
choices=MediaSortChoices.choices,
choices=MediaSortChoices,
)
game_status = models.CharField(
max_length=20,
default=MediaStatusChoices.ALL,
choices=MediaStatusChoices.choices,
choices=MediaStatusChoices,
)
# Media type preferences: Books
@@ -236,17 +236,17 @@ class User(AbstractUser):
book_layout = models.CharField(
max_length=20,
default=LayoutChoices.GRID,
choices=LayoutChoices.choices,
choices=LayoutChoices,
)
book_sort = models.CharField(
max_length=20,
default=MediaSortChoices.SCORE,
choices=MediaSortChoices.choices,
choices=MediaSortChoices,
)
book_status = models.CharField(
max_length=20,
default=MediaStatusChoices.ALL,
choices=MediaStatusChoices.choices,
choices=MediaStatusChoices,
)
# Media type preferences: Comics
@@ -254,17 +254,17 @@ class User(AbstractUser):
comic_layout = models.CharField(
max_length=20,
default=LayoutChoices.GRID,
choices=LayoutChoices.choices,
choices=LayoutChoices,
)
comic_sort = models.CharField(
max_length=20,
default=MediaSortChoices.SCORE,
choices=MediaSortChoices.choices,
choices=MediaSortChoices,
)
comic_status = models.CharField(
max_length=20,
default=MediaStatusChoices.ALL,
choices=MediaStatusChoices.choices,
choices=MediaStatusChoices,
)
# Media type preferences: Board Games
@@ -272,17 +272,17 @@ class User(AbstractUser):
boardgame_layout = models.CharField(
max_length=20,
default=LayoutChoices.GRID,
choices=LayoutChoices.choices,
choices=LayoutChoices,
)
boardgame_sort = models.CharField(
max_length=20,
default=MediaSortChoices.SCORE,
choices=MediaSortChoices.choices,
choices=MediaSortChoices,
)
boardgame_status = models.CharField(
max_length=20,
default=MediaStatusChoices.ALL,
choices=MediaStatusChoices.choices,
choices=MediaStatusChoices,
)
# UI preferences
@@ -295,20 +295,20 @@ class User(AbstractUser):
quick_watch_date = models.CharField(
max_length=20,
default=QuickWatchDateChoices.CURRENT_DATE,
choices=QuickWatchDateChoices.choices,
choices=QuickWatchDateChoices,
help_text="Date to use when bulk-marking media as completed",
)
date_format = models.CharField(
max_length=20,
default=DateFormatChoices.ISO,
choices=DateFormatChoices.choices,
choices=DateFormatChoices,
help_text="Preferred date display format",
)
time_format = models.CharField(
max_length=20,
default=TimeFormatChoices.HOUR_24,
choices=TimeFormatChoices.choices,
choices=TimeFormatChoices,
help_text="Preferred time display format",
)
@@ -341,24 +341,24 @@ class User(AbstractUser):
calendar_layout = models.CharField(
max_length=20,
default=CalendarLayoutChoices.GRID,
choices=CalendarLayoutChoices.choices,
choices=CalendarLayoutChoices,
)
# Lists preferences
lists_sort = models.CharField(
max_length=20,
default=ListSortChoices.LAST_ITEM_ADDED,
choices=ListSortChoices.choices,
choices=ListSortChoices,
)
list_detail_sort = models.CharField(
max_length=20,
default=ListDetailSortChoices.DATE_ADDED,
choices=ListDetailSortChoices.choices,
choices=ListDetailSortChoices,
)
list_detail_status = models.CharField(
max_length=20,
default=MediaStatusChoices.ALL,
choices=MediaStatusChoices.choices,
choices=MediaStatusChoices,
)
# Notification settings

View File

@@ -85,7 +85,7 @@ class NotificationTests(TestCase):
response = self.client.post(
reverse("exclude_notification_item"),
{"item_id": self.item1.id},
HTTP_HX_REQUEST="true",
headers={"hx-request": "true"},
)
self.assertEqual(response.status_code, 200)
@@ -102,7 +102,7 @@ class NotificationTests(TestCase):
response = self.client.post(
reverse("include_notification_item"),
{"item_id": self.item1.id},
HTTP_HX_REQUEST="true",
headers={"hx-request": "true"},
)
self.assertEqual(response.status_code, 200)
@@ -117,7 +117,7 @@ class NotificationTests(TestCase):
response = self.client.get(
reverse("search_notification_items"),
{"q": "Test"},
HTTP_HX_REQUEST="true",
headers={"hx-request": "true"},
)
self.assertEqual(response.status_code, 200)
@@ -131,7 +131,7 @@ class NotificationTests(TestCase):
response = self.client.get(
reverse("search_notification_items"),
{"q": "Test"},
HTTP_HX_REQUEST="true",
headers={"hx-request": "true"},
)
self.assertNotContains(response, "Test Anime")
@@ -142,7 +142,7 @@ class NotificationTests(TestCase):
response = self.client.get(
reverse("search_notification_items"),
{"q": "T"},
HTTP_HX_REQUEST="true",
headers={"hx-request": "true"},
)
self.assertEqual(response.status_code, 200)
@@ -156,7 +156,7 @@ class NotificationTests(TestCase):
response = self.client.get(
reverse("search_notification_items"),
{"q": ""},
HTTP_HX_REQUEST="true",
headers={"hx-request": "true"},
)
self.assertEqual(response.status_code, 200)