Suppose I am in the usual situation where there're extra fields in the many2many relationship:
class Person(models.Model):
name = models.CharField(max_length=128)
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
class Membership(models.Model):
person = models.ForeignKey(Person)
group = models.ForeignKey(Group)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
# other models which are unrelated to the ones above..
class Trip(models.Model):
placeVisited = models.ForeignKey(Place)
visitor = models.ForeignKey(Person)
pleasuretrip = models.Boolean()
class Place(models.Model):
name = models.CharField(max_length=128)
I want to add some extra fields in the Membership form that gets displayed through the Inline. These fields basically are a shortcut to the instantiation of another model (Trip). Trip can have its own admin views, but these shortcuts are needed because when my project partners are entering 'Membership' data in the system they happen to have also the 'Trip' information handy (and also because some of the info in Membership can just be copied over to Trip etc. etc.).
So all I want to have is two extra fields in the Membership Inline - placeVisited and pleasuretrip - which together with the Person instance will let me instantiate the Trip model in the background...
I found out I can easily add extra fields to the inline view by defining my own form. But once the data have been entered, how and when to reference to them in order to perform the save operations I need to do?
class MyForm(forms.ModelForm):
place = forms.ModelChoiceField(required=False, queryset=Place.objects.all(), label="place",)
pleasuretrip = forms.BooleanField(required=False, label="...")
class MembershipInline(admin.TabularInline):
model = Membership
form = MyForm
def save_model(self, request, obj, form, change):
place = form.place
pleasuretrip = form.pleasuretrip
person = form.person
....
# now I can create Trip instances with those data
....
obj.save()
class GroupAdmin(admin.ModelAdmin):
model = Group
....
inlines = (MembershipInline,)
This doesn't seem to work... I'm also a bit puzzled by the save_formset method... maybe is that the one I should be using? Many thanks in advance for the help!!!!
As syn points out in his answer, for TabularInline and StackedInline, you have to override the save_formset method inside the ModelAdmin that contains the inlines.
GroupAdmin(admin.ModelAdmin):
model = Group
....
inlines = (MembershipInline,)
def save_formset(self, request, form, formset, change):
instances = formset.save(commit=False)
for instance in instances:
if isinstance(instance, Member): #Check if it is the correct type of inline
if(not instance.author):
instance.author = request.user
else:
instance.modified_by = request.user
instance.save()
I just hit this same problem, and it seems the solution is that for both save_formset and save_model with inlines, they are not called. Instead you must implement it in the formset which is being called which is the parent e.g.
model = Group
....
inlines = (MembershipInline,)
def save_formset(self, request, form, formset, change):
instances = formset.save(commit=False)
for instance in instances:
# Here an instance is a MembershipInline formset NOT a group...
instance.someunsetfield = something
# I think you are creating new objects, so you could do it here.
instance.save()
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