To add to Kyleβs answer,
Creating a custom form is the only way to set up many, many fields in this way. But, as I discovered, this method only works if you modify an instance of this model. (at least in Django 1.5)
This is because: self.instance returns a Model object. (I know a crazy concept) But if you create an instance of this model since this model has not yet been created, self.instance will throw a DoesNotExist exception.
The way to solve this problem is to create two forms:
class MyModelChangeForm(forms.ModelForm): class Meta: model = MyModel def __init__(self, *args, **kwargs): super(MyModelChangeForm, self).__init__(*args, **kwargs) my_model = self.instance self.fields['fields'].queryset = OtherRelatedModel.objects.filter(other_id=my_model.other) class MyModelCreationForm(forms.ModelForm): class Meta: model = MyModel def save(self, commit=True): my_model = super(MyModelCreationForm, self).save(commit=False) *** Do other things with the my_model if you want *** my_model.save() return my_model
Then inside admin.py we will create a separate set of fields for our creation form:
class MyModelAdmin(admin.ModelAdmin): filter_horizontal = ('other') list_display = ('field1', 'field2' 'field3') fieldsets = ( ("Model info:", {'fields': ("field1", "field2", "field3")}), ("More Model info:", {'fields': ("other",)}), ) add_fieldsets = ( ("Initial info:", {'fields': ("field1", "field2", "field3")}), ) form = MyModelChangeForm add_form = MyModelCreationForm def get_fieldsets(self, request, obj=None): if not obj: return self.add_fieldsets return super(MyModelAdmin, self).get_fieldsets(request, obj) def get_form(self, request, obj=None, **kwargs): """ Use special form during MyModel creation """ defaults = {} if obj is None: defaults.update({ 'form': self.add_form, 'fields': admin.util.flatten_fieldsets(self.add_fieldsets), }) defaults.update(kwargs) return super(MyModelAdmin, self).get_form(request, obj, **defaults)
Note that we had to override get_form and get_fieldsets, if obj is None (or, in other words, if the request needs to add an instance of the model), it uses MyModelCreationForm. This is the same method that django developers use in django.contrib.auth.admin to retrieve their user form and UserCreation fields. (Look aside the source code for this example)
Finally, models will look something like this in model.py:
class MyModel(models.Model): *** field definitions *** other = models.ManytoManyField(OtherRelatedModel, null=True, blank=True) class OtherRelatedModel(models.Model): other_id = model.AutoField(primary_key=True) *** more field definitions ***
The only reason I included models is that you can see the definition of many for many fields in the MyModel class. Y < no null and empty for True. Just remember that if you do not, you will either have to give them a default value in the definition, or set them in the save () function in MyModelCreationForm.
Hope this helps! (If this is completely wrong, please correct me! I need to learn too.)
-Thanks