Source code for users.admin

"""Admin models for the users app."""

from typing import List, Tuple, Type

from django.contrib import admin
from django.contrib.auth import models
from django.db.models.functions import Concat as C
from django.db.models.query import QuerySet, Value as V
from django.forms.fields import BooleanField
from django.forms.models import ModelForm
from django.forms.widgets import CheckboxSelectMultiple
# XXX: Forward reference warning when under TYPE_CHECKING
from django.http import HttpRequest
from django.utils.functional import cached_property
from django.utils.html import format_html

from allauth.account.models import EmailAddress
from allauth.socialaccount.admin import SocialAppAdmin
from allauth.socialaccount.models import SocialAccount, SocialApp, SocialToken

from MangAdventure.filters import boolean_filter

# from commentary.admin import CommentsAdmin
# from commentary.models import Comment

[docs]class UserTypeFilter(admin.SimpleListFilter): """Admin interface filter for user types.""" #: The title of the filter. title = 'type' #: The filter's query parameter. parameter_name = 'type'
[docs] def lookups(self, request: 'HttpRequest', model_admin: Type[admin.ModelAdmin]) -> List[Tuple[str, str]]: """ Return a list of lookups for this filter. The first element in each tuple is the value of the query parameter. The second element is the human-readable name for the option that will appear in the admin sidebar. :param request: The original request. :param model_admin: An admin model object. :return: The following list of tuples: .. code-block:: python [ ('superuser', 'Superuser'), ('staff', 'Staff'), ('scanlator', 'Scanlator'), ('regular', 'Regular') ] """ return [ ('superuser', 'Superuser'), ('staff', 'Staff'), ('scanlator', 'Scanlator'), ('regular', 'Regular') ]
[docs] def queryset(self, request: 'HttpRequest', queryset: 'QuerySet') -> 'QuerySet': """ Return the filtered queryset based on the value provided in the query string. :param request: The original request. :param queryset: The original queryset. :return: A filtered queryset according to :meth:`lookups`. """ return { 'superuser': queryset.filter(is_superuser=True), 'staff': queryset.filter(is_staff=True), 'scanlator': queryset.filter(groups__name='Scanlator'), 'regular': queryset.exclude(is_staff=True) }.get(self.value(), queryset)
[docs]class User(models.User): """:class:`django.contrib.auth.models.User` proxy model.""" @cached_property def is_scanlator(self) -> bool: """Get the scanlator status of the user.""" return self.groups.filter(name='Scanlator').exists() class Meta: proxy = True auto_created = True app_label = 'users' verbose_name = 'user'
[docs]class UserForm(ModelForm): """Admin form for :class:`User`.""" #: Scanlator status. is_scanlator = BooleanField( label='Scanlator status', required=False, help_text=( 'Designates whether the user has ' '"groups" and "reader" permissions.' ) ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['is_scanlator'].initial = \ 'instance' in kwargs and self.instance.is_scanlator
[docs] def save(self, commit: bool = True) -> User: # pragma: no cover is_scanlator = self.cleaned_data.pop('is_scanlator', False) instance = super().save(commit=False) if is_scanlator and not instance.is_scanlator: instance.groups.add( models.Group.objects.get(name='Scanlator') ) if commit: elif not is_scanlator and instance.is_scanlator: instance.groups.remove( models.Group.objects.get(name='Scanlator') ) if commit: return instance
[docs] class Meta: model = User fields = '__all__'
[docs]class UserAdmin(admin.ModelAdmin): """Admin model for :class:`User`.""" form = UserForm exclude = ('password', 'groups') list_display = ( 'username', '_email', 'full_name', 'date_joined', 'is_active' ) list_editable = ('is_active',) search_fields = ('username', 'email', 'first_name', 'last_name') list_filter = ( boolean_filter('status', 'is_active', ('Active', 'Inactive')), UserTypeFilter, ) ordering = ('username',) def _email(self, obj: User) -> str: if not return '' return format_html( '<a href="mailto:{0}" rel="noopener noreferrer"' ' target="_blank">{0}</a>', ) _email.short_description = 'e-mail address' _email.admin_order_field = 'email'
[docs] def full_name(self, obj: User) -> str: """ Get the full name of the user. :param obj: A ``User`` model instance. :return: The user's full name. """ return obj.get_full_name()
full_name.admin_order_field = C('first_name', V(' '), 'last_name')
[docs] def has_add_permission(self, request: 'HttpRequest') -> bool: """ Return whether adding an ``User`` object is permitted. :param request: The original request. :return: Always returns ``False``. """ return False
[docs]class OAuthApp(SocialApp): """:class:`allauth.socialaccount.models.SocialApp` proxy model.""" class Meta: proxy = True auto_created = True app_label = 'users' verbose_name = 'OAuth app'
[docs] def __str__(self) -> str: """ Return a string representing the object. :return: The name and provider of the app. """ return f'{} ({self.provider})'
[docs]class OAuthAppAdmin(SocialAppAdmin): """Admin model for :class:`OAuthApp`.""" list_display = ('name', '_provider', 'client_id') radio_fields = {'provider': admin.HORIZONTAL}
[docs] def get_form(self, *args, **kwargs) -> ModelForm: # pragma: no cover form = super().get_form(*args, **kwargs) form.base_fields['sites'].widget.widget = CheckboxSelectMultiple() return form
def _provider(self, obj: OAuthApp) -> str: if not obj.provider: return '' return format_html( '<a href="{}{}" rel="noopener noreferrer" target="_blank">{}</a>', '', obj.provider, obj.provider.capitalize() ) _provider.short_description = 'provider' _provider.admin_order_field = 'provider'
# class UserComment(Comment): # class Meta: # proxy = True # auto_created = True # app_label = 'users' # class UserCommentAdmin(CommentsAdmin): # def has_add_permission(self, request): # return False EmailAddress, SocialAccount, SocialToken, SocialApp, models.User, models.Group )), UserAdmin), OAuthAppAdmin) #, UserCommentAdmin) __all__ = [ 'UserTypeFilter', 'User', 'UserForm', 'UserAdmin', 'OAuthApp', 'OAuthAppAdmin' ]