Skip to content

Commit f1df62a

Browse files
authored
Create admin.py
0 parents  commit f1df62a

File tree

1 file changed

+168
-0
lines changed

1 file changed

+168
-0
lines changed

admin.py

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
from django.contrib import admin
2+
from django.forms.models import modelform_factory
3+
4+
# Imports for Dynamic app registrations
5+
from django.apps import apps
6+
7+
# Models
8+
from web.models import *
9+
10+
# Json Widget
11+
# from web.widget import JsonEditorWidget
12+
13+
14+
15+
# CONFIG CONSTANTS
16+
admin.site.site_header = 'WOLFx Admin'
17+
exempt = [] # modelname in this list will not be registered
18+
global_app_name = 'web' # Replace '' with your app name
19+
20+
21+
# ADMIN.PY MAIN CODE
22+
class GenericStackedAdmin(admin.StackedInline):
23+
extra = 1
24+
25+
# This method ensures the field order is correct for inlines as well
26+
def get_formset(self, request, obj=None, **kwargs):
27+
formset = super().get_formset(request, obj, **kwargs)
28+
form = formset.form
29+
custom_order = [field for field in form.base_fields if field not in CommonModel._meta.fields]
30+
custom_order += [field for field in CommonModel._meta.fields if field in form.base_fields]
31+
form.base_fields = {field: form.base_fields[field] for field in custom_order}
32+
return formset
33+
34+
35+
class GenericAdmin(admin.ModelAdmin):
36+
def __init__(self, model, admin_site):
37+
self.model = model
38+
self.inlines = []
39+
self.actions = []
40+
self.admin_meta = getattr(model, 'admin_meta', {})
41+
42+
# Dynamic admin meta from model
43+
# Specify a static dictionary in model
44+
try:
45+
# Admin Meta
46+
if model.admin_meta:
47+
for k,v in model.admin_meta.items():
48+
self.__setattr__(k,v)
49+
except:
50+
pass
51+
52+
# Dynamic Actions from model
53+
# Specify a key 'actions' in the admin_meta dictionary in model
54+
try:
55+
if 'actions' in model.admin_meta:
56+
for action_name in model.admin_meta['actions']:
57+
# Ensure action_name is a string
58+
if isinstance(action_name, str):
59+
action_function = getattr(model, action_name, None)
60+
if callable(action_function):
61+
self.add_action(action_function, action_name)
62+
except Exception as e:
63+
# Handle or log the exception
64+
pass
65+
66+
# Register Inlines
67+
self.register_inlines()
68+
69+
super().__init__(model, admin_site)
70+
71+
def formfield_for_dbfield(self, db_field, request, **kwargs):
72+
# Check if the field is a JSONField
73+
if isinstance(db_field, models.JSONField) and self.admin_meta:
74+
# Retrieve the schema configuration for JSON fields
75+
json_fields_meta = self.model.admin_meta.get('json_fields', {})
76+
77+
# Retrieve the schema for the specific field, if defined
78+
json_schema = json_fields_meta.get(db_field.name, {}).get('schema')
79+
80+
if json_schema:
81+
# Initialize the custom widget with the specified schema
82+
kwargs['widget'] = JsonEditorWidget(schema=json_schema)
83+
else:
84+
# Else load the django-jsoneditor widget
85+
kwargs['widget'] = JSONEditor()
86+
87+
return super().formfield_for_dbfield(db_field, request, **kwargs)
88+
89+
# Function to get the fieldsets
90+
def get_fieldsets(self, request, obj=None):
91+
# If admin meta has fieldssets defined then return that fieldsets
92+
if 'fieldsets' in self.admin_meta:
93+
return self.admin_meta['fieldsets']
94+
95+
# Define the fieldsets
96+
common_fields = [field.name for field in CommonModel._meta.fields if field.editable]
97+
other_fields = [field.name for field in self.model._meta.fields if (field.name not in common_fields and field.editable and field.name != 'id')]
98+
m2m_fields = [field.name for field in self.model._meta.many_to_many]
99+
other_fields = other_fields + m2m_fields
100+
101+
fieldsets = [
102+
(self.model._meta.object_name, {
103+
'fields': other_fields,
104+
}),
105+
('Meta Data', {
106+
'fields': common_fields,
107+
}),
108+
]
109+
110+
return fieldsets
111+
112+
def get_readonly_fields(self, request, obj=None):
113+
# Get a list of non-editable fields
114+
readonly_fields = [field.name for field in self.model._meta.fields if (not field.editable or field.name == 'id')]
115+
116+
return readonly_fields
117+
118+
# Function to add actions to the admin class
119+
def add_action(self, action_function, action_name):
120+
def wrapper_action(modeladmin, request, queryset):
121+
for obj in queryset:
122+
action_method = getattr(obj, action_name)
123+
if callable(action_method):
124+
action_method(request)
125+
126+
wrapper_action.__name__ = f'admin_action_{action_name}' # Change the name
127+
wrapper_action.short_description = action_name.replace('_', ' ').title()
128+
129+
if not hasattr(self, 'actions') or not self.actions:
130+
self.actions = [wrapper_action]
131+
else:
132+
# Prevent re-adding the same action
133+
if wrapper_action not in self.actions:
134+
self.actions.append(wrapper_action)
135+
136+
self.__dict__[wrapper_action.__name__] = wrapper_action
137+
138+
def register_inlines(self):
139+
if hasattr(self.model, 'admin_meta') and 'inline' in self.model.admin_meta:
140+
for inline_info in self.model.admin_meta['inline']:
141+
for related_model, fk_name in inline_info.items():
142+
self.add_inline(related_model, fk_name)
143+
144+
def add_inline(self, related_model_name, fk_name):
145+
related_model = apps.get_model(app_label=global_app_name, model_name=related_model_name) # Replace 'your_app_name'
146+
inline_class_name = f"{related_model.__name__}Inline"
147+
148+
class_attrs = {
149+
'model' : related_model,
150+
'fk_name' : fk_name,
151+
'form' : modelform_factory(related_model, exclude=[]),
152+
}
153+
154+
InlineAdminClass = type(inline_class_name, (GenericStackedAdmin,), class_attrs)
155+
self.inlines.append(InlineAdminClass)
156+
157+
# Custom Media so that we can add custom js files
158+
class Media:
159+
js = ('https://code.jquery.com/jquery-3.7.0.js', )
160+
161+
162+
app = apps.get_app_config(global_app_name)
163+
for model_name, model in app.models.items():
164+
# If model_name consists history
165+
if model_name not in exempt and 'histor' not in model_name.lower():
166+
# print(model_name + ' ' + str(model))
167+
admin.site.register(model, GenericAdmin)
168+

0 commit comments

Comments
 (0)