Refactor test utilities and enhance ASGI settings

- Cleaned up and standardized assertions in ApiTestMixin for API response validation.
- Updated ASGI settings to use os.environ for setting the DJANGO_SETTINGS_MODULE.
- Removed unused imports and improved formatting in settings.py.
- Refactored URL patterns in urls.py for better readability and organization.
- Enhanced view functions in views.py for consistency and clarity.
- Added .flake8 configuration for linting and style enforcement.
- Introduced type stubs for django-environ to improve type checking with Pylance.
This commit is contained in:
pacnpal
2025-08-20 19:51:59 -04:00
parent 69c07d1381
commit 66ed4347a9
230 changed files with 15094 additions and 11578 deletions

View File

@@ -3,8 +3,8 @@ Selectors for user and account-related data retrieval.
Following Django styleguide pattern for separating data access from business logic.
"""
from typing import Optional, Dict, Any, List
from django.db.models import QuerySet, Q, F, Count, Avg, Prefetch
from typing import Dict, Any
from django.db.models import QuerySet, Q, F, Count
from django.contrib.auth import get_user_model
from django.utils import timezone
from datetime import timedelta
@@ -15,212 +15,259 @@ User = get_user_model()
def user_profile_optimized(*, user_id: int) -> Any:
"""
Get a user with optimized queries for profile display.
Args:
user_id: User ID
Returns:
User instance with prefetched related data
Raises:
User.DoesNotExist: If user doesn't exist
"""
return User.objects.prefetch_related(
'park_reviews',
'ride_reviews',
'socialaccount_set'
).annotate(
park_review_count=Count('park_reviews', filter=Q(park_reviews__is_published=True)),
ride_review_count=Count('ride_reviews', filter=Q(ride_reviews__is_published=True)),
total_review_count=F('park_review_count') + F('ride_review_count')
).get(id=user_id)
return (
User.objects.prefetch_related(
"park_reviews", "ride_reviews", "socialaccount_set"
)
.annotate(
park_review_count=Count(
"park_reviews", filter=Q(park_reviews__is_published=True)
),
ride_review_count=Count(
"ride_reviews", filter=Q(ride_reviews__is_published=True)
),
total_review_count=F("park_review_count") + F("ride_review_count"),
)
.get(id=user_id)
)
def active_users_with_stats() -> QuerySet:
"""
Get active users with review statistics.
Returns:
QuerySet of active users with review counts
"""
return User.objects.filter(
is_active=True
).annotate(
park_review_count=Count('park_reviews', filter=Q(park_reviews__is_published=True)),
ride_review_count=Count('ride_reviews', filter=Q(ride_reviews__is_published=True)),
total_review_count=F('park_review_count') + F('ride_review_count')
).order_by('-total_review_count')
return (
User.objects.filter(is_active=True)
.annotate(
park_review_count=Count(
"park_reviews", filter=Q(park_reviews__is_published=True)
),
ride_review_count=Count(
"ride_reviews", filter=Q(ride_reviews__is_published=True)
),
total_review_count=F("park_review_count") + F("ride_review_count"),
)
.order_by("-total_review_count")
)
def users_with_recent_activity(*, days: int = 30) -> QuerySet:
"""
Get users who have been active in the last N days.
Args:
days: Number of days to look back for activity
Returns:
QuerySet of recently active users
"""
cutoff_date = timezone.now() - timedelta(days=days)
return User.objects.filter(
Q(last_login__gte=cutoff_date) |
Q(park_reviews__created_at__gte=cutoff_date) |
Q(ride_reviews__created_at__gte=cutoff_date)
).annotate(
recent_park_reviews=Count('park_reviews', filter=Q(park_reviews__created_at__gte=cutoff_date)),
recent_ride_reviews=Count('ride_reviews', filter=Q(ride_reviews__created_at__gte=cutoff_date)),
recent_total_reviews=F('recent_park_reviews') + F('recent_ride_reviews')
).order_by('-last_login').distinct()
return (
User.objects.filter(
Q(last_login__gte=cutoff_date)
| Q(park_reviews__created_at__gte=cutoff_date)
| Q(ride_reviews__created_at__gte=cutoff_date)
)
.annotate(
recent_park_reviews=Count(
"park_reviews",
filter=Q(park_reviews__created_at__gte=cutoff_date),
),
recent_ride_reviews=Count(
"ride_reviews",
filter=Q(ride_reviews__created_at__gte=cutoff_date),
),
recent_total_reviews=F("recent_park_reviews") + F("recent_ride_reviews"),
)
.order_by("-last_login")
.distinct()
)
def top_reviewers(*, limit: int = 10) -> QuerySet:
"""
Get top users by review count.
Args:
limit: Maximum number of users to return
Returns:
QuerySet of top reviewers
"""
return User.objects.filter(
is_active=True
).annotate(
park_review_count=Count('park_reviews', filter=Q(park_reviews__is_published=True)),
ride_review_count=Count('ride_reviews', filter=Q(ride_reviews__is_published=True)),
total_review_count=F('park_review_count') + F('ride_review_count')
).filter(
total_review_count__gt=0
).order_by('-total_review_count')[:limit]
return (
User.objects.filter(is_active=True)
.annotate(
park_review_count=Count(
"park_reviews", filter=Q(park_reviews__is_published=True)
),
ride_review_count=Count(
"ride_reviews", filter=Q(ride_reviews__is_published=True)
),
total_review_count=F("park_review_count") + F("ride_review_count"),
)
.filter(total_review_count__gt=0)
.order_by("-total_review_count")[:limit]
)
def moderator_users() -> QuerySet:
"""
Get users with moderation permissions.
Returns:
QuerySet of users who can moderate content
"""
return User.objects.filter(
Q(is_staff=True) |
Q(groups__name='Moderators') |
Q(user_permissions__codename__in=['change_parkreview', 'change_ridereview'])
).distinct().order_by('username')
return (
User.objects.filter(
Q(is_staff=True)
| Q(groups__name="Moderators")
| Q(
user_permissions__codename__in=[
"change_parkreview",
"change_ridereview",
]
)
)
.distinct()
.order_by("username")
)
def users_by_registration_date(*, start_date, end_date) -> QuerySet:
"""
Get users who registered within a date range.
Args:
start_date: Start of date range
end_date: End of date range
Returns:
QuerySet of users registered in the date range
"""
return User.objects.filter(
date_joined__date__gte=start_date,
date_joined__date__lte=end_date
).order_by('-date_joined')
date_joined__date__gte=start_date, date_joined__date__lte=end_date
).order_by("-date_joined")
def user_search_autocomplete(*, query: str, limit: int = 10) -> QuerySet:
"""
Get users matching a search query for autocomplete functionality.
Args:
query: Search string
limit: Maximum number of results
Returns:
QuerySet of matching users for autocomplete
"""
return User.objects.filter(
Q(username__icontains=query) |
Q(first_name__icontains=query) |
Q(last_name__icontains=query),
is_active=True
).order_by('username')[:limit]
Q(username__icontains=query)
| Q(first_name__icontains=query)
| Q(last_name__icontains=query),
is_active=True,
).order_by("username")[:limit]
def users_with_social_accounts() -> QuerySet:
"""
Get users who have connected social accounts.
Returns:
QuerySet of users with social account connections
"""
return User.objects.filter(
socialaccount__isnull=False
).prefetch_related(
'socialaccount_set'
).distinct().order_by('username')
return (
User.objects.filter(socialaccount__isnull=False)
.prefetch_related("socialaccount_set")
.distinct()
.order_by("username")
)
def user_statistics_summary() -> Dict[str, Any]:
"""
Get overall user statistics for dashboard/analytics.
Returns:
Dictionary containing user statistics
"""
total_users = User.objects.count()
active_users = User.objects.filter(is_active=True).count()
staff_users = User.objects.filter(is_staff=True).count()
# Users with reviews
users_with_reviews = User.objects.filter(
Q(park_reviews__isnull=False) |
Q(ride_reviews__isnull=False)
).distinct().count()
users_with_reviews = (
User.objects.filter(
Q(park_reviews__isnull=False) | Q(ride_reviews__isnull=False)
)
.distinct()
.count()
)
# Recent registrations (last 30 days)
cutoff_date = timezone.now() - timedelta(days=30)
recent_registrations = User.objects.filter(
date_joined__gte=cutoff_date
).count()
recent_registrations = User.objects.filter(date_joined__gte=cutoff_date).count()
return {
'total_users': total_users,
'active_users': active_users,
'inactive_users': total_users - active_users,
'staff_users': staff_users,
'users_with_reviews': users_with_reviews,
'recent_registrations': recent_registrations,
'review_participation_rate': (users_with_reviews / total_users * 100) if total_users > 0 else 0
"total_users": total_users,
"active_users": active_users,
"inactive_users": total_users - active_users,
"staff_users": staff_users,
"users_with_reviews": users_with_reviews,
"recent_registrations": recent_registrations,
"review_participation_rate": (
(users_with_reviews / total_users * 100) if total_users > 0 else 0
),
}
def users_needing_email_verification() -> QuerySet:
"""
Get users who haven't verified their email addresses.
Returns:
QuerySet of users with unverified emails
"""
return User.objects.filter(
is_active=True,
emailaddress__verified=False
).distinct().order_by('date_joined')
return (
User.objects.filter(is_active=True, emailaddress__verified=False)
.distinct()
.order_by("date_joined")
)
def users_by_review_activity(*, min_reviews: int = 1) -> QuerySet:
"""
Get users who have written at least a minimum number of reviews.
Args:
min_reviews: Minimum number of reviews required
Returns:
QuerySet of users with sufficient review activity
"""
return User.objects.annotate(
park_review_count=Count('park_reviews', filter=Q(park_reviews__is_published=True)),
ride_review_count=Count('ride_reviews', filter=Q(ride_reviews__is_published=True)),
total_review_count=F('park_review_count') + F('ride_review_count')
).filter(
total_review_count__gte=min_reviews
).order_by('-total_review_count')
return (
User.objects.annotate(
park_review_count=Count(
"park_reviews", filter=Q(park_reviews__is_published=True)
),
ride_review_count=Count(
"ride_reviews", filter=Q(ride_reviews__is_published=True)
),
total_review_count=F("park_review_count") + F("ride_review_count"),
)
.filter(total_review_count__gte=min_reviews)
.order_by("-total_review_count")
)