0
# Django Admin Integration
1
2
Complete Django admin interface integration with custom admin classes, forms, and filters for preference management. This provides a user-friendly web interface for managing preferences through Django's built-in admin system.
3
4
## Capabilities
5
6
### Dynamic Preference Admin
7
8
Base admin class for preference models with customized display, filtering, and editing capabilities.
9
10
```python { .api }
11
class DynamicPreferenceAdmin(admin.ModelAdmin):
12
"""
13
Base admin class for preference models.
14
15
Attributes:
16
- list_display: Shows verbose_name, name, section_name, help_text, raw_value, default_value
17
- readonly_fields: name, section_name, default_value
18
- search_fields: name, section, raw_value
19
- list_filter: section (with SectionFilter)
20
"""
21
list_display = ('verbose_name', 'name', 'section_name', 'help_text', 'raw_value', 'default_value')
22
readonly_fields = ('name', 'section_name', 'default_value')
23
search_fields = ('name', 'section', 'raw_value')
24
list_filter = ('section',)
25
26
def default_value(self, obj):
27
"""
28
Display the default value for the preference.
29
30
Args:
31
- obj: Preference model instance
32
33
Returns:
34
String representation of default value
35
"""
36
37
def section_name(self, obj):
38
"""
39
Display the section verbose name.
40
41
Args:
42
- obj: Preference model instance
43
44
Returns:
45
Section verbose name or section name
46
"""
47
48
def save_model(self, request, obj, form, change):
49
"""
50
Handle preference updates through preference manager.
51
52
Args:
53
- request: HTTP request
54
- obj: Preference model instance
55
- form: Admin form
56
- change: Whether this is an update (True) or create (False)
57
"""
58
```
59
60
### Global Preference Admin
61
62
Admin class specifically for global preferences with appropriate form configuration.
63
64
```python { .api }
65
class GlobalPreferenceAdmin(DynamicPreferenceAdmin):
66
"""
67
Admin class for global preferences.
68
69
Attributes:
70
- form: GlobalSinglePreferenceForm
71
- changelist_form: GlobalSinglePreferenceForm
72
"""
73
form = GlobalSinglePreferenceForm
74
changelist_form = GlobalSinglePreferenceForm
75
```
76
77
### Per Instance Preference Admin
78
79
Base admin class for per-instance preferences with instance field management.
80
81
```python { .api }
82
class PerInstancePreferenceAdmin(DynamicPreferenceAdmin):
83
"""
84
Base admin class for per-instance preferences.
85
86
Attributes:
87
- list_display: Adds "instance" to parent list_display
88
- fields: Adds "instance" to parent fields
89
- raw_id_fields: ("instance",) for better performance with large datasets
90
- form: SinglePerInstancePreferenceForm
91
"""
92
raw_id_fields = ('instance',)
93
form = SinglePerInstancePreferenceForm
94
95
def get_list_display(self, request):
96
"""Add instance to list display."""
97
98
def get_fields(self, request, obj=None):
99
"""Add instance to form fields."""
100
```
101
102
### Section Filter
103
104
Custom admin list filter for filtering preferences by section with user-friendly section names.
105
106
```python { .api }
107
class SectionFilter(admin.SimpleListFilter):
108
"""
109
Admin list filter for preference sections.
110
111
Displays section verbose names when available,
112
falling back to section names for better UX.
113
"""
114
title = 'section'
115
parameter_name = 'section'
116
117
def lookups(self, request, model_admin):
118
"""
119
Return list of section choices for filtering.
120
121
Returns:
122
List of tuples (section_name, section_display_name)
123
"""
124
125
def queryset(self, request, queryset):
126
"""
127
Filter queryset by selected section.
128
129
Args:
130
- request: HTTP request
131
- queryset: Base queryset
132
133
Returns:
134
Filtered queryset
135
"""
136
```
137
138
## Usage Examples
139
140
### Basic Admin Registration
141
142
```python
143
# admin.py
144
from django.contrib import admin
145
from dynamic_preferences.admin import GlobalPreferenceAdmin
146
from dynamic_preferences.models import GlobalPreferenceModel
147
148
# Register global preferences with custom admin
149
admin.site.register(GlobalPreferenceModel, GlobalPreferenceAdmin)
150
```
151
152
### Custom Admin Class
153
154
```python
155
from dynamic_preferences.admin import DynamicPreferenceAdmin
156
from myapp.models import MyPreferenceModel
157
158
class MyPreferenceAdmin(DynamicPreferenceAdmin):
159
# Customize list display
160
list_display = DynamicPreferenceAdmin.list_display + ('custom_field',)
161
162
# Add custom filtering
163
list_filter = DynamicPreferenceAdmin.list_filter + ('custom_field',)
164
165
# Add custom search fields
166
search_fields = DynamicPreferenceAdmin.search_fields + ('custom_field',)
167
168
def custom_field(self, obj):
169
"""Custom field display method."""
170
return obj.some_custom_logic()
171
custom_field.short_description = 'Custom Field'
172
173
admin.site.register(MyPreferenceModel, MyPreferenceAdmin)
174
```
175
176
### User Preference Admin
177
178
```python
179
from dynamic_preferences.users.admin import UserPreferenceAdmin
180
from dynamic_preferences.users.models import UserPreferenceModel
181
182
# The UserPreferenceAdmin is already configured for user preferences
183
admin.site.register(UserPreferenceModel, UserPreferenceAdmin)
184
185
# Custom user preference admin
186
class CustomUserPreferenceAdmin(UserPreferenceAdmin):
187
# Show username in list display
188
list_display = UserPreferenceAdmin.list_display + ('get_username',)
189
190
# Filter by user groups
191
list_filter = UserPreferenceAdmin.list_filter + ('instance__groups',)
192
193
def get_username(self, obj):
194
"""Display username for the preference."""
195
return obj.instance.username if obj.instance else 'N/A'
196
get_username.short_description = 'Username'
197
get_username.admin_order_field = 'instance__username'
198
```
199
200
### Inline Admin for Related Models
201
202
```python
203
from django.contrib import admin
204
from dynamic_preferences.admin import PerInstancePreferenceAdmin
205
206
class PreferenceInline(admin.TabularInline):
207
"""Inline admin for preferences on related model admin."""
208
model = MyPreferenceModel
209
extra = 0
210
readonly_fields = ('name', 'section', 'default_value')
211
fields = ('name', 'section', 'value', 'default_value')
212
213
class MyModelAdmin(admin.ModelAdmin):
214
inlines = [PreferenceInline]
215
216
admin.site.register(MyModel, MyModelAdmin)
217
```
218
219
### Custom Form Integration
220
221
```python
222
from dynamic_preferences.admin import DynamicPreferenceAdmin
223
from dynamic_preferences.forms import GlobalSinglePreferenceForm
224
225
class CustomPreferenceForm(GlobalSinglePreferenceForm):
226
"""Custom form with additional validation."""
227
228
def clean(self):
229
cleaned_data = super().clean()
230
# Add custom validation logic
231
if self.preference and self.preference.name == 'sensitive_setting':
232
if not self.request.user.is_superuser:
233
raise ValidationError('Only superusers can modify this setting')
234
return cleaned_data
235
236
class CustomPreferenceAdmin(DynamicPreferenceAdmin):
237
form = CustomPreferenceForm
238
239
def get_form(self, request, obj=None, **kwargs):
240
"""Pass request to form for user-based validation."""
241
form = super().get_form(request, obj, **kwargs)
242
form.request = request
243
return form
244
```
245
246
### Bulk Actions
247
248
```python
249
class BulkPreferenceAdmin(DynamicPreferenceAdmin):
250
"""Admin with bulk actions for preference management."""
251
252
actions = ['reset_to_default', 'mark_as_configured']
253
254
def reset_to_default(self, request, queryset):
255
"""Reset selected preferences to their default values."""
256
count = 0
257
for pref in queryset:
258
if pref.preference:
259
pref.value = pref.preference.default
260
pref.save()
261
count += 1
262
263
self.message_user(
264
request,
265
f'Successfully reset {count} preferences to default values.'
266
)
267
reset_to_default.short_description = 'Reset selected preferences to default'
268
269
def mark_as_configured(self, request, queryset):
270
"""Custom bulk action example."""
271
# Custom logic here
272
pass
273
mark_as_configured.short_description = 'Mark as configured'
274
```
275
276
### Advanced Filtering
277
278
```python
279
class AdvancedSectionFilter(admin.SimpleListFilter):
280
"""Advanced section filter with grouping."""
281
title = 'section group'
282
parameter_name = 'section_group'
283
284
def lookups(self, request, model_admin):
285
sections = set()
286
for pref in model_admin.model.objects.all():
287
if pref.section:
288
# Group sections by prefix
289
section_group = pref.section.split('_')[0] if '_' in pref.section else pref.section
290
sections.add(section_group)
291
292
return [(group, group.title()) for group in sorted(sections)]
293
294
def queryset(self, request, queryset):
295
if self.value():
296
return queryset.filter(section__startswith=self.value())
297
return queryset
298
299
class AdvancedPreferenceAdmin(DynamicPreferenceAdmin):
300
list_filter = DynamicPreferenceAdmin.list_filter + (AdvancedSectionFilter,)
301
```