Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 42 additions & 5 deletions apps/contributor/admin.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import typing

from admin_auto_filters.filters import AutocompleteFilterFactory
from django.contrib import admin
from django.db import models
from django.db.models.functions import Coalesce
from django.http import HttpRequest
from django.urls import reverse
from django.utils.html import format_html
from djangoql.admin import DjangoQLSearchMixin # type: ignore[reportMissingTypeStubs]
Expand All @@ -23,9 +27,12 @@ class ContributorUserAdmin(DjangoQLSearchMixin, admin.ModelAdmin): # type: igno
"modified_at",
)
list_display = ("firebase_id", "username", "team", "created_at")
list_filter = (
AutocompleteFilterFactory("Team", "team"),
"created_at",
)
ordering = ("username", "team", "created_at")
search_fields = ("username",)
# list_filter = ("team",)
list_select_related = True
autocomplete_fields = ("team",)

Expand Down Expand Up @@ -65,19 +72,49 @@ class ContributorTeamAdmin(
UserResourceAdmin,
admin.ModelAdmin, # type: ignore[reportMissingTypeArgument]
):
list_display = ("name", "view_team_members")
list_display = (
"name",
"members_count",
)
ordering = ("name",)
search_fields = ("name",)
list_select_related = True

@typing.override
def get_queryset(self, request: HttpRequest) -> models.QuerySet[ContributorTeam]:
return (
super()
.get_queryset(request)
.annotate(
members_count=Coalesce(
models.Subquery(
ContributorUser.objects.filter(
team=models.OuterRef("id"),
)
.order_by()
.values("team")
.annotate(c=models.Count("id"))
.values("c")[:1],
output_field=models.IntegerField(),
),
0,
),
)
)

@typing.override
def save_model(self, request, obj, form, change): # type: ignore[reportMissingParameterType]
super().save_model(request, obj, form, change)
FirebaseContributorTeam(obj).trigger()

def view_team_members(self, obj): # type: ignore[reportMissingParameterType]
url = reverse("admin:contributor_contributoruser_changelist") + f"?team__id__exact={obj.id}"
return format_html('<a href="{}">View Team Members</a>', url)
@admin.display(ordering="members_count", description="Members count")
def members_count(self, obj: ContributorTeam):
url = reverse("admin:contributor_contributoruser_changelist") + f"?team={obj.id}"
return format_html(
'<a href="{}">{}</a>',
url,
obj.members_count, # type: ignore[reportAttributeAccessIssue]
)


@admin.register(ContributorUserGroupMembership)
Expand Down
2 changes: 1 addition & 1 deletion main/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class Key:
@staticmethod
@contextmanager
def redis_lock(lock_id: str, *, lock_expire: int | None = None):
lock_expire_ = lock_expire or settings.REDIS_LOCK_EXPIRE
lock_expire_ = lock_expire or settings.DEFAULT_REDIS_LOCK_EXPIRE
timeout_at: float = time.monotonic() + lock_expire_ - 3
# cache.add fails if the key already exists
status = cache.add(lock_id, 1, lock_expire_)
Expand Down
10 changes: 6 additions & 4 deletions main/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ def urlparse(value) -> ParseResult:
"djangoql",
"rest_framework",
"drf_spectacular",
"admin_auto_filters",
# - Health-check
"health_check", # required
"health_check.db",
Expand Down Expand Up @@ -406,7 +407,7 @@ def urlparse(value) -> ParseResult:
)

# Redis lock
REDIS_LOCK_EXPIRE = 60 * 10 # Lock expires in 10min (in seconds)
DEFAULT_REDIS_LOCK_EXPIRE = 60 * 10 # Lock expires in 10min (in seconds)

# Cache
CACHE_REDIS_URL = env("CACHE_REDIS_URL")
Expand All @@ -419,9 +420,10 @@ def urlparse(value) -> ParseResult:
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
},
"local-memory": {
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
},
"KEY_PREFIX": "djc-",
},
"local-memory": {
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
},
}

Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ dependencies = [
"django-storages[s3]",
"djangoql", # Admin panel query search
"djangorestframework",
"django-admin-autocomplete-filter",
"drf-spectacular",
"factory-boy~=3.2.1",
"gunicorn~=20.1.0",
Expand Down
14 changes: 14 additions & 0 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading