Runcible
Runcible

Reputation: 3098

Django admin - Foreign key popup '+' missing when overriding admin form field

I've set up a basic django site using the automatic admin, and was using the '+' button to add foreign keys (plants) while adding an Ingredient. However, the plants weren't ordered so I've had to override the form field as show below.

It seems though that doing this means the '+' button which opened the popup has gone missing - is there a simple way to reinclude this, or a better way I should be ordering the foreign key dropdown? Thanks.

class IngredientAdminForm(forms.ModelForm):
    plant = forms.ModelChoiceField(queryset=Plant.objects.order_by('name'), required=False)

    class Meta:
        model = Ingredient


class IngredientAdmin(admin.ModelAdmin):
    list_display = ('name', 'description', 'plant')
    form = IngredientAdminForm

Upvotes: 1

Views: 2545

Answers (1)

Alasdair
Alasdair

Reputation: 308909

Firstly, have you set a default ordering for your model? It might make more sense to set the ordering there than in the admin.

class Plant(models.Model):
    name = models.CharField(max_length=30)

    class Meta:
        ordering = ['name',]

If you want a different ordering in a form, then changing the queryset is ok. Note that out don't need to explicitly define the plant field in your form -- you can change the queryset in your __init__ method.

class IngredientAdminForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(IngredientAdminForm, self).__init__(*args, **kwargs)
        self.fields['plant'].queryset = Plant.objects.order_by('name')

    class Meta:
        model = Ingredient

In the Django admin, you don't actually have to define a custom model form. You can use the model admin method formfield_for_foreignkey.

class IngredientAdmin(admin.ModelAdmin): 
    list_display = ('name', 'description', 'plant')

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "plant":
            kwargs["queryset"] = Plant.objects.order_by('name')
            return db_field.formfield(**kwargs)
        return super(IngredientAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)

Upvotes: 1

Related Questions