如何为要在表单中使用的 Django 模型字段生成选择元组

How to generate a choices tuple for django models field to use in a form

正在尝试创建基于另一个模型的选择字段

我希望我的选择被映射为 username: first_name + last_name

当我尝试 username: last_name 时它确实有效

我试过这样做(注意,我正在添加 user_choices 和 choices=user_choices。在我进行这些更改之前该模型已经存在。)

这个有效:

he_user_choices = tuple(User.objects.values_list('username', 'last_name'))

这是我的 models.py 的样子:

from django.contrib.auth.models import User

owner_choices = tuple(User.objects.values_list('username', 'first_name' + 'last_name'))


class ErrorEvent(models.Model):
    """Error Event Submissions"""
    event_id = models.BigAutoField(primary_key=True)
    owner = models.IntegerField(verbose_name="Owner", blank=True, choices=owner_choices)

这是我的 forms.py

from django import forms
from .models import ErrorEvent


class ErrorEventForm(forms.ModelForm):

    class Meta:
        model = ErrorEvent
        # fields =
        exclude = ['event_id']
        widgets = {
            'owner': forms.Select(),
        }

目前 owner_choices 不起作用,我收到一条错误消息:

django.core.exceptions.AppRegistryNotReady: Models aren't loaded yet.

关于我还可以尝试什么的任何建议,或者我将如何解决我的问题?

提前致谢!

不要使用IntegerField来引用一个对象。 ForeignKey 将检查参照完整性,而且它使 Django ORM 更具表现力。

因此您可以通过以下方式实现:

from django.conf import settings

class ErrorEvent(models.Model):
    event_id = models.BigAutoField(primary_key=True)
    owner = models.<b>ForeignKey(</b>
        settings.AUTH_USER_MODEL,
        verbose_name='Owner',
        blank=True,
        null=True
    <b>)</b>

这将与 ModelChoiceField [Django-doc] 一起工作,后者会自动查询数据库以呈现选项。这也意味着如果您添加一个新的 User,创建一个新的 ErrorEvent 可以链接到该用户,因为它每次都从数据库请求 User

您可以子类化 ModelChoiceField 以指定如何显示选项,例如:

from django.forms import ModelChoiceField

class MyUserModelChoiceField(ModelChoiceField):

    def <b>label_from_instance</b>(self, obj):
        return f'{obj.username} ({obj.firstname} {obj.lastname})'

然后我们可以用这个形式:

class ErrorEventForm(forms.ModelForm):
    <b>owner = MyUserModelChoiceField(queryset=User.objects.all())</b>

    class Meta:
        model = ErrorEvent
        # fields =
        exclude = ['event_id']
        widgets = {
            'owner': forms.Select(),
        }