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?