File: admin.py

package info (click to toggle)
python-django-waffle 4.2.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 684 kB
  • sloc: python: 3,266; makefile: 139; sh: 39; javascript: 34
file content (149 lines) | stat: -rwxr-xr-x 4,747 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
from __future__ import annotations

from typing import Any

from django.contrib import admin
from django.contrib.admin.models import LogEntry, CHANGE, DELETION
from django.contrib.admin.widgets import ManyToManyRawIdWidget
from django.contrib.contenttypes.models import ContentType
from django.http import HttpRequest
from django.utils.html import escape
from django.utils.translation import gettext_lazy as _

from waffle.models import Flag, Sample, Switch
from waffle.utils import get_setting


class BaseAdmin(admin.ModelAdmin):
    search_fields = ('name', 'note')

    def get_actions(self, request: HttpRequest) -> dict[str, Any]:
        actions = super().get_actions(request)
        if 'delete_selected' in actions:
            del actions['delete_selected']
        return actions


def _add_log_entry(user, model, description, action_flag):
    LogEntry.objects.create(
        user=user,
        content_type=ContentType.objects.get_for_model(type(model)),
        object_id=model.id,
        object_repr=model.name + " " + description,
        action_flag=action_flag
    )


@admin.action(
    description=_('Enable selected flags for everyone'),
    permissions=('change',),
)
def enable_for_all(ma, request, qs):
    # Iterate over all objects to cause cache invalidation.
    for f in qs.all():
        _add_log_entry(request.user, f, "on", CHANGE)
        f.everyone = True
        f.save()


@admin.action(
    description=_('Disable selected flags for everyone'),
    permissions=('change',),
)
def disable_for_all(ma, request, qs):
    # Iterate over all objects to cause cache invalidation.
    for f in qs.all():
        _add_log_entry(request.user, f, "off", CHANGE)
        f.everyone = False
        f.save()


@admin.action(
    description=_('Delete selected'),
    permissions=('delete',),
)
def delete_individually(ma, request, qs):
    # Iterate over all objects to cause cache invalidation.
    for f in qs.all():
        _add_log_entry(request.user, f, "deleted", DELETION)
        f.delete()


class InformativeManyToManyRawIdWidget(ManyToManyRawIdWidget):
    """Widget for ManyToManyField to Users.

    Will display the names of the users in a parenthesised list after the
    input field. This widget works with all models that have a "name" field.
    """
    def label_and_url_for_value(self, values: Any) -> tuple[str, str]:
        names = []
        key = self.rel.get_related_field().name
        for value in values:
            try:
                name = self.rel.model._default_manager \
                    .using(self.db) \
                    .get(**{key: value})
                names.append(escape(str(name)))
            except self.rel.model.DoesNotExist:
                names.append('<missing>')
        return "(" + ", ".join(names) + ")", ""


class FlagAdmin(BaseAdmin):
    actions = [enable_for_all, disable_for_all, delete_individually]
    list_display = ('name', 'note', 'everyone', 'percent', 'superusers',
                    'staff', 'authenticated', 'languages')
    list_filter = ('everyone', 'superusers', 'staff', 'authenticated')
    raw_id_fields = ('users', )
    ordering = ('-id',)

    def formfield_for_dbfield(self, db_field, **kwargs):
        if db_field.name == 'users':
            kwargs.pop('request', None)
            kwargs['widget'] = \
                InformativeManyToManyRawIdWidget(db_field.remote_field,
                                                 self.admin_site,
                                                 using=kwargs.get("using"))
            return db_field.formfield(**kwargs)
        return super().formfield_for_dbfield(db_field, **kwargs)


@admin.action(
    description=_('Enable selected switches'),
    permissions=('change',),
)
def enable_switches(ma, request, qs):
    for switch in qs:
        _add_log_entry(request.user, switch, "on", CHANGE)
        switch.active = True
        switch.save()


@admin.action(
    description=_('Disable selected switches'),
    permissions=('change',),
)
def disable_switches(ma, request, qs):
    for switch in qs:
        _add_log_entry(request.user, switch, "off", CHANGE)
        switch.active = False
        switch.save()


class SwitchAdmin(BaseAdmin):
    actions = [enable_switches, disable_switches, delete_individually]
    list_display = ('name', 'active', 'note', 'created', 'modified')
    list_filter = ('active',)
    ordering = ('-id',)


class SampleAdmin(BaseAdmin):
    actions = [delete_individually]
    list_display = ('name', 'percent', 'note', 'created', 'modified')
    ordering = ('-id',)


if get_setting('ENABLE_ADMIN_PAGES'):
    admin.site.register(Flag, FlagAdmin)
    admin.site.register(Sample, SampleAdmin)
    admin.site.register(Switch, SwitchAdmin)