简体   繁体   中英

Django overriding display names for foreign key field in modelform

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?

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,
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM