I have a form with KeywordInline
. When I add new object using the form inlined formset has a js-link to add new form into formset. Newly added forms have a js-enabled delete button (x mark on the right).
KeywordInline
class KeywordInline(admin.TabularInline):
fields = ('word',)
model = models.Keyword
formset = forms.KeywordFromset
verbose_name = _('Keyword')
verbose_name_plural = _('Keywords')
extra = 1
can_delete = True
def get_readonly_fields(self, request, obj=None):
if obj:
if str(obj.status) == 'Finished':
self.extra = 0
self.can_delete = False
self.max_num = obj.keyword_set.count()
return ('word',)
self.extra = 1
self.can_delete = True
self.max_num = None
return []
KeywordFromset
class KeywordFromset(BaseInlineFormSet):
def clean(self):
super(KeywordFromset, self).clean()
formset_keywords = set()
for form in self.forms:
if not getattr(form, 'cleaned_data', {}).get('word', None):
keyword = None
else:
keyword = form.cleaned_data['word']
if keyword in formset_keywords:
form._errors['word'] = ErrorList([_(self.get_unique_error_message([_('Keyword')]))])
else:
formset_keywords.add(keyword)
Now if I hit save button and ValidationError rises those delete buttons disappears from fromset. So if I've added wrong keyword mistakenly I cannot delete it.
Is this normal behaviour? And how can I make delete links persist?
Any help is much appreciated.
Django formset allows you to edit a collection of the same forms on the same page. It basically allows you to bulk edit a collection of objects at the same time.
By default, formset_factory() defines one extra form; the following example will create a formset class to display two blank forms: >>> ArticleFormSet = formset_factory(ArticleForm, extra=2) Iterating over a formset will render the forms in the order they were created.
Django model formsets provide a way to edit or create multiple model instances within a single form. Model Formsets are created by a factory method. The default factory method is modelformset_factory(). It wraps formset factory to model forms. We can also create inlineformset_factory() to edit related objects.
There's no delete link for the inlines that triggered ValidationError since they aren't yet saved to a database, hence no delete link.
I realize it's inconsistent behavior (since you can delete those rows before hitting "save" button, but you can't once they triggered validation errors), but its normal, default way of how Django does it.
To fix this, you could override the template for inline and make the delete buttons appear despite validation errors.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With