Note that there are some explanatory texts on larger screens.

plurals
  1. PODjango replace ModelForm instance dynamically OR don't save Form data [image]
    text
    copied!<p>data entry people keep adding and duplicating models because they can't easily search for an existing item inline so I added fields to the Brand ModelForm to allow autosuggesting a Brand model.</p> <h1>The Problem</h1> <p>Brand.name is a required field by the Brand model. Thus when only the Autocomplete field is filled (in the case of reassigning an existing Brand to the current company) the form.save() fails (its empty but a Brand.name is required by save() and in any case I don't want to save the form as a model instance as I've just reassigned ). </p> <p>If a Brand is submitted in the reassign field, I want to just set that Brands.company to the parent formset value, and silently return without trying to save the ModelForm.</p> <p>The relation is a Foreign Key from Brand Model to the Company model - a company may have many Brands. </p> <p>A picture says a thousand words so... </p> <p><img src="https://i.stack.imgur.com/yvgmH.png" alt="enter image description here"></p> <h1>Code</h1> <pre><code>class BrandAdminForm(forms.ModelForm): reassign_existing = AutoCompleteSelectField('brand', required=False,) confirm_reassign = BooleanField(required=False, help_text=_("Are you sure you want to reassign the brand?")) def __init__(self, *args, **kwargs): super(BrandAdminForm, self).__init__(*args, **kwargs) self.fields['name'].required = False def clean(self): cleaned_data = super(BrandAdminForm, self).clean() import ipdb; ipdb.set_trace() if cleaned_data['reassign_existing'] \ and cleaned_data['confirm_reassign'] \ and not self.instance.pk: self.instance = cleaned_data['reassign_existing'] cleaned_data['reassign_existing'].company = self.instance.company cleaned_data['id'] = self.instance.id cleaned_data['category'] = self.instance.category.all() cleaned_data['website'] = self.instance.website cleaned_data['twitter_handle'] = self.instance.twitter_handle cleaned_data['wikipedia_uri'] = self.instance.wikipedia_uri cleaned_data['email'] = self.instance.email cleaned_data['name'] = self.instance.name return cleaned_data elif cleaned_data['reassign_existing'] \ and cleaned_data['confirm_reassign'] \ and self.instance.pk: raise forms.ValidationError("You can't reassign AND add/edit a brand in the same form. Clear one of the sections.") else: if not cleaned_data['name']: msg = u"You must add a name to a new brand." self._errors["name"] = self.error_class([msg]) return cleaned_data class Meta: model = Brand </code></pre> <p>This approach almost works, only when reassigning a Brand's Categories are being list. This is M2M field. </p> <h1>Edit 1</h1> <p>I tried to override the save to not save when there is value in 'reassign_existing' but end up with a </p> <pre><code>'NoneType' object has no attribute 'company_id' </code></pre> <p>this is the setup</p> <pre><code>class BrandAdminForm(forms.ModelForm): reassign_existing = AutoCompleteSelectField('brand', required=False, ) confirm_reassign = BooleanField(required=False, help_text=_("Are you sure you want to reassign the brand?")) def __init__(self, *args, **kwargs): super(BrandAdminForm, self).__init__(*args, **kwargs) self.fields['name'].required = False def clean(self): cleaned_data = super(BrandAdminForm, self).clean() if cleaned_data['reassign_existing'] \ and cleaned_data['confirm_reassign'] \ and not self.instance.pk: cleaned_data['reassign_existing'].company = self.instance.company cleaned_data['reassign_existing'].save() return cleaned_data elif cleaned_data['reassign_existing'] \ and cleaned_data['confirm_reassign'] \ and self.instance.pk: raise forms.ValidationError("You can't reassign AND add/edit a brand in the same form. Clear one of the sections.") else: if not cleaned_data['name']: msg = u"You must add a name to a new brand." self._errors["name"] = self.error_class([msg]) return cleaned_data def save(self, *args, **kwargs): if not self.cleaned_data['reassign_existing']: super(BrandAdminForm, self).save(*args, **kwargs) class Meta: model = Brand </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload