Предварительное заполнение набора форм django определенными значениями
Я неделями мучаюсь с ModelFormSet & co, голова взрывается. Я искал часами, днями в интернете, чтобы найти решение, но ничего действительно полезного для моей особой проблемы:
У меня есть 2 модели (здесь упрощенно):
class BaseSetting(models.Model):
"""This is a basic model which holds namespace and key of a setting."""
namespace = models.CharField(max_length=25)
key = models.CharField(max_length=255)
class ScopedSetting(models.Model):
"""Model class for all scoped MedUX settings.
Settings are generally saved as strings, but are interpreted at retrieval
and casted into their correct types. ScopedSettings knows about
``str``, ``int``, ``bool``"""
base = models.ForeignKey(BaseSetting, on_delete=models.CASCADE)
"""The FK to the basic settings fields like namespace, key."""
tenant = models.ForeignKey(
Tenant,
verbose_name=_("Tenant"),
on_delete=models.CASCADE,
default=None,
null=True,
blank=True,
)
group = models.ForeignKey(
Group, on_delete=models.CASCADE, default=None, null=True, blank=True
)
device = models.ForeignKey(
Device, on_delete=models.CASCADE, default=None, null=True, blank=True
)
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
default=None,
null=True,
blank=True,
)
scope = models.IntegerField(choices=Scope.choices)
"""The scope where this setting is valid."""
value = models.CharField(max_length=255, null=True)
ATM Я использую django-extra-views, чтобы получить простой ModelFormSetView
- и он показывает форму, но не то, что я хочу:
Для каждой базовой настройки (пространство имен, ключ) существует до 5 различных ScopedSetting
, которые могут быть применимы к текущему пользователю, в зависимости от их области применения: поставщик, текущий арендатор, группа, устройство или пользователь: Таким образом, каждый пользователь может иметь собственную настройку, каждый арендатор и т.д., но пользовательская настройка для одного пользователя, если она доступна как объект БД, перекрывает настройку поставщика. Существует четкая система разрешений и каскад диапазонов для проверки того, какая настройка применима, и все это работает. Я просто хочу отредактировать эти настройки.
Итак, я хотел бы иметь представление под /settings/<base_setting_pk>/
, которое показывает в основном (упрощенно, это даже сложнее) все 5 диапазонов: VENDOR, TENANT, GROUP, DEVICE, USER.
Это идеальный вариант использования для набора форм ИМХО, НО: он должен показывать все эти 5 настроек, даже если они отсутствуютв БД.
Здесь появляется extra=...
, и я могу показать правильное количество предметов.
class BaseSettingsDetailView(HtmxMixin, ModelFormSetView):
# ScopedPermissionRequiredMixin,
model = ScopedSettings
form_class = ScopedSettingsForm
formset = ScopedSettingsModelFormSet
fields = ["value", "scope"]
enforce_htmx = False
ordering = ["scope"]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def setup(self, request, *args, **kwargs):
super().setup(request, *args, **kwargs)
self.base_instance = self.get_queryset().first().base
self.scopes = SettingsRegistry.scopes(
self.base_instance.namespace, self.base_instance.key
)
self.additional = []
def get_queryset(self):
return super().get_queryset().filter(base_id=self.kwargs.get("pk"))
def get_factory_kwargs(self):
def formfield_callback(field_name) -> forms.Field:
print(field_name)
if field_name:
return forms.CharField()
for scope in self.scopes:
if self.get_queryset().filter(scope=scope.value).exists():
pass
else:
self.additional.append(
ScopedSettings(base=self.base_instance, scope=scope)
)
factory_kwargs = super().get_factory_kwargs()
max_num = len(self.get_queryset()) + len(self.additional)
factory_kwargs.update(
{"max_num": max_num, "formfield_callback": formfield_callback}
)
return factory_kwargs
Но я не могу заставить форму отображать правильные данные в пустых, неинициализированных, дополнительных полях: Они просто помечены как "значение".
Мне нужно 5 полей, каждое из которых помечено областью видимости. Некоторые из них должны быть заполнены набором запросов (это может быть первый и третий, например), а остальные должны быть пустыми, но обозначены правильно (и предварительно заполнены недостающей областью видимости, каждый)
Надеюсь, это понятно.
Любая подсказка приветствуется.