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)
|