That question might look similar to this one, but it's not...
I have a model structure like :
class Customer(models.Model): .... class CustomerCompany(models.Model): customer = models.ForeignKey(Customer) type = models.SmallIntegerField(....)
I am using InlineModels
, and have two types of CustomerCompany.type
. So I define two different inlines for the CustomerCompany
and override InlineModelAdmin.queryset
class CustomerAdmin(admin.ModelAdmin): inlines=[CustomerCompanyType1Inline, CustomerCompanyType2Inline] class CustomerCompanyType1Inline(admin.TabularInline): model = CustomerCompany def queryset(self, request): return super(CustomerCompanyType1Inline, self).queryset(request).filter(type=1) class CustomerCompanyType2Inline(admin.TabularInline): model = CustomerCompany def queryset(self, request): return super(CustomerCompanyType2Inline, self).queryset(request).filter(type=2)
All is nice and good up to here, but for adding new records for InlineModelAdmin
, I still need to display type
field of CustomerCompany
on the AdminForm
, since I can not override save
method of an InlineModelAdmin
like:
class CustomerCompanyType2Inline(admin.TabularInline): model = CustomerCompany def queryset(self, request): return super(CustomerCompanyType2Inline, self).queryset(request).filter(type=2) #Following override do not work def save_model(self, request, obj, form, change): obj.type=2 obj.save()
Using a signal is also not a solution since my signal sender
will be the same Model
, so I can not detect which InlineModelAdmin
send it and what the type
must be...
Is there a way that will let me set type
field before save?
save() method from its parent class is to be overridden so we use super keyword. slugify is a function that converts any string into a slug. so we are converting the title to form a slug basically.
Creating objects To create an object, instantiate it using keyword arguments to the model class, then call save() to save it to the database. This performs an INSERT SQL statement behind the scenes. Django doesn't hit the database until you explicitly call save() . The save() method has no return value.
Alasdair's answer isn't wrong, but it has a few sore points that could cause problems. First, by looping through the formset using form
as the variable name, you actually override the value passed into the method for form
. It's not a huge deal, but since you can do the save without commit right from the formset, it's better to do it that way. Second, the all important formset.save_m2m()
was left out of the answer. The actual Django docs recommend the following:
def save_formset(self, request, form, formset, change): instances = formset.save(commit=False) for instance in instances: # Do something with `instance` instance.save() formset.save_m2m()
The problem you're going to run into is that the save_formset
method must go on the parent ModelAdmin
rather than the inlines, and from there, there's no way to know which inline is actually being utilized. If you have an obj with two "types" and all the fields are the same, then you should be using proxy models and you can actually override the save method of each to set the appropriate type automatically.
class CustomerCompanyType1(CustomerCompany): class Meta: proxy = True def save(self, *args, **kwargs): self.type = 1 super(CustomerCompanyType1, self).save(*args, **kwargs) class CustomerCompanyType2(CustomerCompany): class Meta: proxy = True def save(self, *args, **kwargs): self.type = 2 super(CustomerCompanyType2, self).save(*args, **kwargs)
Then, you don't need to do anything special at all with your inlines. Just change your existing inline admin classes to use their appropriate proxy model, and everything will sort itself out.
There's a save_formset
method which you could override. You'd have to work out which inline the formset
represents somehow.
def save_formset(self, request, form, formset, change): instances = formset.save(commit=False) for instance in instances: # Do something with `instance` instance.save() formset.save_m2m()
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