Reputation: 4008
I have 2 models A and B; When a B instance is created in django Admin, I want the foreign key to be automatically added.
In the examples below I try to use a custom form, but I tried also to use the save
in the model, but there a ValidationError
is not raised
I have the following code:
in models:
class A(models.model):
content = models.TextField()
Class B(models.model):
a = models.ForeignKey(A, related_name='bs', on_delete=models.CASCADE)
content = models.TextField()
in form:
class AdminBModelForm(forms.ModelForm):
class Meta:
model = B
fields = ['content']
def save(self, commit=True):
obj = super().save(commit=False)
obj.a_id = A.objects.first()
if obj.a_id is None:
raise ValidationError('You first need to set A')
obj.save()
return obj
in admin:
class BAdmin(admin.ModelAdmin):
model = B
form = AdminBModelForm
The error: IntegrityError - null value in column "_id" violates not-null constraint
Upvotes: 0
Views: 1901
Reputation: 309089
Firstly, note that you shouldn't assign model objects to the a_id
field. You can either do:
obj.a = A.objects.first()
or:
a = A.objects.first()
if a is not None:
obj.a_id = a.id
Next, if you cannot guarantee that A.objects.first()
is not None
, then you need to check that in the clean
method. It is too late to raise validation errors in the save
or save_model
methods.
class AdminBModelForm(forms.ModelForm):
def clean(self):
cleaned_data = super().clean()
if not A.objects.exists():
raise forms.ValidationError("Cannot save B until an A has been created")
return cleaned_data
Finally, a common approach so set values in the Django admin is to override the save_model
method.
class BAdmin(admin.ModelAdmin):
model = B
fields = ['content']
def save_model(self, request, obj, form, change):
obj.a = A.objects.first()
super().save_model(request, obj, form, change)
Upvotes: 4
Reputation: 253
There is a slight error in assigning A object. Try this:
class AdminBModelForm(forms.ModelForm):
class Meta:
model = B
fields = ['content']
def save(self, commit=True):
obj = super(AdminBModelForm, self).save(commit=False)
obj.a = A.objects.first() # Assigning the object reference
if not obj.a: # No need to check for None explicitly
raise ValidationError('You first need to set A')
obj.save()
return obj
Upvotes: 0