Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django overriding display names for foreign key field in modelform

Tags:

python

django

Suppose below models:

from django.db import models


class Status:
    name = models.CharField(max_length=50)
    order = models.PositiveIntegerField()

    def __str__(self):
        return self.name

class Article:
    headline = models.CharField(max_length=100)
    status = models.ForeignKey(Status, on_delete=models.CASCADE, null=True)

I want to create admin form for Article model, but don't want to use results of __str__ method of Status model as display name in status choices form field. It can be achieved by overriding label_from_instance method ModelChoiceField as below:

from django import forms

from blog.models import Status, Article

class StatusModelChoiceField(forms.ModelChoiceField):
    def label_from_instance(self, status):
        label = f"{status.order}: {status.name}"

        return label

class ArticleForm(forms.ModelForm):
    status = StatusModelChoiceField(queryset = Status.objects.all())

    class Meta:
        model = Article
        fields = ('headline', 'status')

Problem with this method is that, it doesn't take into account Article model's status field definition. For example, although status field is nullable in Article model, it is required in ArticleForm. I should tell explicitly that it is not required (status = StatusModelChoiceField(queryset = Status.objects.all(), required=False)). If status field would have limit_choices_to, it also won't be considered in my form dynamically.

So, I just want different display names than default __str__. How can I achieve this goal in more DRY manner?

like image 799
Elgin Cahangirov Avatar asked Aug 31 '25 20:08

Elgin Cahangirov


1 Answers

Although you will have to make the custom field inheriting from ModelChoiceField, what you can do is set it as the class to be used for your field by using the field_classes attribute one can set on the forms Meta (Reference Overriding the default fields [Django docs]):

class ArticleForm(forms.ModelForm):

    class Meta:
        model = Article
        fields = ('headline', 'status')
        field_classes = {
            'status': StatusModelChoiceField,
        }
like image 108
Abdul Aziz Barkat Avatar answered Sep 04 '25 03:09

Abdul Aziz Barkat