Я следовал этому: https://www.yergler.net/2009/09/27/nested-formsets-with-django/ и это: встроенные формы django со сложной моделью для вложенной формы, и в целом мой код отлично работает.
class Account(models.Model):
user_username = models.ForeignKey(User, on_delete=models.CASCADE)
account_name = models.CharField(max_length=30)
class Classification(models.Model):
user_username=models.ForeignKey(User, on_delete=models.CASCADE)
data_id=models.ForeignKey(ImportData, on_delete=models.CASCADE)
class ImportData(models.Model):
user_username = models.ForeignKey(User, on_delete=models.CASCADE)
data_id = models.UUIDField(
primary_key=True, default=uuid.uuid4, editable=False)
ClassificationFormset = inlineformset_factory(ImportData, Classification, exclude=('user_username',), extra=1)
# below is just what came from the nested formset links above: pasted here for easy reference.
class BaseNestedTransactionFormset(BaseInlineFormSet):
def add_fields(self, form, index):
# allow the super class to create the fields as usual
super(BaseNestedTransactionFormset, self).add_fields(form, index)
try:
instance = self.get_queryset()[index]
pk_value = instance.pk
except IndexError:
instance=None
pk_value = hash(form.prefix)
transaction_data = None
if (self.data):
transaction_data = self.data;
# store the formset in the .nested property
form.nested = [
CategoryFormset(data=transaction_data,
instance = instance,
prefix = 'CAT_%s' % pk_value)]
def is_valid(self):
result = super(BaseNestedTransactionFormset, self).is_valid()
for form in self.forms:
if hasattr(form, 'nested'):
for n in form.nested:
# make sure each nested formset is valid as well
result = result and n.is_valid()
return result
def save_new(self, form, commit=True):
"""Saves and returns a new model instance for the given form."""
instance = super(BaseNestedTransactionFormset, self).save_new(form, commit=commit)
# update the form’s instance reference
form.instance = instance
# update the instance reference on nested forms
for nested in form.nested:
nested.instance = instance
# iterate over the cleaned_data of the nested formset and update the foreignkey reference
for cd in nested.cleaned_data:
cd[nested.fk.name] = instance
return instance
def save_all(self, commit=True):
"""Save all formsets and along with their nested formsets."""
# Save without committing (so self.saved_forms is populated)
# — We need self.saved_forms so we can go back and access
# the nested formsets
objects = self.save(commit=False)
# Save each instance if commit=True
if commit:
for o in objects:
o.save()
# save many to many fields if needed
if not commit:
self.save_m2m()
# save the nested formsets
for form in set(self.initial_forms + self.saved_forms):
# if self.should_delete(form): continue
for nested in form.nested:
nested.save(commit=commit)
ImportTransactionFormset = inlineformset_factory(Account, ImportData, exclude=('user_username',), formset=BaseNestedTransactionFormset, extra=0)
В моем шаблоне есть таблица, в которой отображается набор форм импорта данных... пользователь выбирает учетную запись, и в таблице отображаются все импортированные данные из этой учетной записи. Для каждой из этих форм строк внизу есть скрытая строка... пользователь нажимает кнопку, чтобы отобразить эту скрытую строку. Скрытая строка отображает вложенный набор форм классификации.
Если включить поле user_username в шаблон и разрешить ему быть частью вложенного набора форм в шаблоне, я могу установить его соответственно в форме html, и наборы форм не сохранятся.
Однако: я хочу иметь возможность исключить поле user_username из шаблона, а мое представление или какой-либо другой метод в классе BaseNestedTransactionFormset установить значение поля user_username в значение request.user для всех, кто вошел в систему в это время.
Я попытался переопределить метод очистки, но clean_data выдает ошибку, потому что форма не проходит проверку; поле обязательно. Кажется, я не могу придумать хороший способ сделать это.
Если бы это был обычный набор форм, это было бы не так сложно сделать. Я бы просто установил поле, изменив то, что возвращается от POST. Я никогда не работал с вложенными встроенными формами, и меня достали префиксы и индексы в именах полей. Я был в этом в течение нескольких дней и, похоже, никуда не денется.
Я также подумываю просто избавиться от этого поля из модели классификации, поскольку оно уже привязано к модели ImportData, которая независимо связана с вошедшим в систему пользователем. Я просто думаю, что могу снова столкнуться с этим в какой-то момент, так что, может быть, хорошо решить.
Заранее спасибо.