feat(config): implement field customization in settings.toml

MK/conditional_fields
mariusrklein 4 months ago
parent f58a7dc4b6
commit c7d1a16cb3

@ -8,8 +8,10 @@ from django.http import HttpResponse, HttpResponseRedirect
from django.urls import path, reverse
from django.db import models
from django.contrib.admin import helpers, widgets
from django.conf import settings
import rules.contrib.admin
from rules.permissions import perm_exists
from utils import OrderedSet
class FieldPermissionsAdminMixin:
@ -175,6 +177,62 @@ class CommonAdminMixin(FieldPermissionsAdminMixin, ChangeViewAdminMixin, Filtere
# For any other type of field, just call its formfield() method.
return db_field.formfield(**kwargs)
@property
def field_key(self):
return f"{self.model._meta.app_label}_{self.model.__name__}".lower()
def get_excluded_fields(self):
return OrderedSet(settings.CUSTOM_MODEL_FIELDS.get(self.field_key, {}).get('exclude', []))
def get_included_fields(self):
return OrderedSet(settings.CUSTOM_MODEL_FIELDS.get(self.field_key, {}).get('fields', []))
def get_fieldsets(self, request, obj=None):
included = self.get_included_fields()
excluded = self.get_excluded_fields()
original_fieldsets = super().get_fieldsets(request, obj)
if original_fieldsets:
print(f"get_fieldsets called for {self.field_key}")
print(f"Original fieldsets: {original_fieldsets}")
new_fieldsets = []
for title, attrs in original_fieldsets:
fields = attrs.get("fields", [])
# Flatten groupings like tuples if needed
filtered_fields = [
f for f in fields
if (
(not included or f in included)
and f not in excluded
)
]
if filtered_fields:
new_fieldsets.append((title, dict(attrs, **{"fields": filtered_fields})))
if new_fieldsets:
print(f"Filtered fieldsets: {new_fieldsets}")
return new_fieldsets
def get_fields(self, request, obj=None):
fields = OrderedSet(super().get_fields(request, obj) or [])
custom_fields = self.get_included_fields() - self.get_excluded_fields()
if custom_fields:
print(f"get_fields called for {self.field_key}, fields: {fields}, custom_fields: {custom_fields}")
return list(custom_fields)
return list(fields)
def get_exclude(self, request, obj=None):
excluded = OrderedSet(super().get_exclude(request, obj) or [])
custom_excluded = self.get_excluded_fields() - self.get_included_fields()
if custom_excluded:
print(f"get_exclude called for {self.field_key}, excluded: {excluded}, custom_excluded: {custom_excluded}")
return list(excluded | custom_excluded)
return list(excluded)
class CommonAdminInlineMixin(CommonAdminMixin):
def has_add_permission(self, request, obj):

@ -76,3 +76,8 @@ REPORTS_SECTION = get_var('startpage', 'reports_section', default='reports')
# testing
TEST_MAIL = get_var('testing', 'mail', default='test@localhost')
# excluded and included model fields in admin and admin forms
CUSTOM_MODELS = list(get_var('custom_model_fields', default={}).keys())
CUSTOM_MODEL_FIELDS = {model.lower(): get_var('model_fields', model, default=[]) for model in CUSTOM_MODELS}

@ -5,6 +5,7 @@ from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
from decimal import Decimal, ROUND_HALF_DOWN
import unicodedata
from collections import OrderedDict
def file_size_validator(max_upload_size):
@ -88,3 +89,28 @@ def coming_midnight():
return timezone.datetime(year=base.year, month=base.month, day=base.day,
hour=0, minute=0, second=0, microsecond=0,
tzinfo=base.tzinfo)
class OrderedSet(OrderedDict):
def __init__(self, iterable=None):
super().__init__()
if iterable:
for item in iterable:
self[item] = None
def __sub__(self, other):
if not isinstance(other, OrderedSet):
return NotImplemented
return OrderedSet(k for k in self if k not in other)
def add(self, item):
self[item] = None
def discard(self, item):
self.pop(item, None)
def __contains__(self, item):
return item in self.keys()
def __iter__(self):
return iter(self.keys())
Loading…
Cancel
Save