2024-08-01 17:02:29 +00:00
|
|
|
from typing import Annotated
|
|
|
|
|
|
|
|
from annotated_types import MinLen
|
2024-09-17 10:10:06 +00:00
|
|
|
from django.contrib.staticfiles.storage import staticfiles_storage
|
2024-08-01 17:02:29 +00:00
|
|
|
from django.db.models import Q
|
|
|
|
from django.utils.text import slugify
|
|
|
|
from haystack.query import SearchQuerySet
|
|
|
|
from ninja import FilterSchema, ModelSchema, Schema
|
|
|
|
from pydantic import AliasChoices, Field
|
2024-07-18 18:23:30 +00:00
|
|
|
|
|
|
|
from core.models import User
|
|
|
|
|
|
|
|
|
|
|
|
class SimpleUserSchema(ModelSchema):
|
|
|
|
"""A schema with the minimum amount of information to represent a user."""
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
model = User
|
|
|
|
fields = ["id", "nick_name", "first_name", "last_name"]
|
|
|
|
|
|
|
|
|
2024-09-17 10:10:06 +00:00
|
|
|
class UserProfileSchema(ModelSchema):
|
|
|
|
"""The necessary information to show a user profile"""
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
model = User
|
|
|
|
fields = ["id", "nick_name", "first_name", "last_name"]
|
|
|
|
|
|
|
|
display_name: str
|
|
|
|
profile_url: str
|
|
|
|
profile_pict: str
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def resolve_display_name(obj: User) -> str:
|
|
|
|
return obj.get_display_name()
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def resolve_profile_url(obj: User) -> str:
|
|
|
|
return obj.get_absolute_url()
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def resolve_profile_pict(obj: User) -> str:
|
|
|
|
if obj.profile_pict_id is None:
|
|
|
|
return staticfiles_storage.url("core/img/unknown.jpg")
|
|
|
|
return obj.profile_pict.get_download_url()
|
|
|
|
|
|
|
|
|
2024-08-01 17:02:29 +00:00
|
|
|
class UserFilterSchema(FilterSchema):
|
|
|
|
search: Annotated[str, MinLen(1)]
|
|
|
|
exclude: list[int] | None = Field(
|
|
|
|
None, validation_alias=AliasChoices("exclude", "exclude[]")
|
|
|
|
)
|
|
|
|
|
|
|
|
def filter_search(self, value: str | None) -> Q:
|
|
|
|
if not value:
|
|
|
|
return Q()
|
2024-09-17 15:52:39 +00:00
|
|
|
if len(value) < 3:
|
2024-08-01 17:02:29 +00:00
|
|
|
# For small queries, full text search isn't necessary
|
|
|
|
return (
|
|
|
|
Q(first_name__istartswith=value)
|
|
|
|
| Q(last_name__istartswith=value)
|
|
|
|
| Q(nick_name__istartswith=value)
|
|
|
|
)
|
|
|
|
return Q(
|
|
|
|
id__in=list(
|
|
|
|
SearchQuerySet()
|
|
|
|
.models(User)
|
|
|
|
.autocomplete(auto=slugify(value).replace("-", " "))
|
|
|
|
.values_list("pk", flat=True)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
def filter_exclude(self, value: set[int] | None) -> Q:
|
|
|
|
if not value:
|
|
|
|
return Q()
|
|
|
|
return ~Q(id__in=value)
|
|
|
|
|
|
|
|
|
|
|
|
class MarkdownSchema(Schema):
|
|
|
|
text: str
|
|
|
|
|
|
|
|
|
2024-09-17 10:10:06 +00:00
|
|
|
class FamilyGodfatherSchema(Schema):
|
|
|
|
godfather: int
|
|
|
|
godchild: int
|
|
|
|
|
|
|
|
|
|
|
|
class UserFamilySchema(Schema):
|
|
|
|
"""Represent a graph of a user's family"""
|
|
|
|
|
|
|
|
users: list[UserProfileSchema]
|
|
|
|
relationships: list[FamilyGodfatherSchema]
|