akm*_*akm 2 django django-models django-forms
我只想列出 OneToOneField 中可用的项目,而不是所有项目,它不像在 ChoiceField 中过滤值,因为我们需要找出可以使用的值,这是基于是否已使用的原则。
我的模型定义如下:
class Foo(models.Model):
somefield = models.CharField(max_length=12)
class Bar(models.Model):
somefield = models.CharField(max_length=12)
foo = models.OneToOneField(Foo)
Run Code Online (Sandbox Code Playgroud)
现在我使用 ModelForm 创建基于 Bar 模型的表单,如下所示:
class BarForm(ModelForm):
class Meta:
model = Bar
Run Code Online (Sandbox Code Playgroud)
现在问题在于它使用 HTML 的选择小部件在 ChoiceField 中显示数据库中可用的所有 Foo 对象的列表,因为该字段是 OneToOneField django 将强制将 Bar 对象与 Foo 对象进行单一关联,但因为它显示列表中的所有可用和不可用项目很难找出表单中可接受的值,并且用户被迫使用点击/试用方法来找出正确的选项。
如何更改此行为并仅列出字段中可以使用的项目?
虽然这是一个古老的话题,但我在寻找相同的答案时遇到了它。
调整 BarForm,使其看起来像:
class BarForm(ModelForm):
class Meta:
model = Bar
def __init__(self, *args, **kwargs):
super(BarForm, self).__init__(*args, **kwargs)
#only provide Foos that are not already linked to a Bar, plus the Foo that was already chosen for this Bar
self.fields['foo'].queryset = Foo.objects.filter(Q(bar__isnull=True)|Q(bar=self.instance))
Run Code Online (Sandbox Code Playgroud)
这应该够了吧。您覆盖 init 函数,以便可以编辑表单中的 foo 字段,为其提供更具体的可用 Foo 和(相当重要)已选择的 Foo 的查询集。
我最初的问题是:如何仅显示一对一关系上的可用用户?
我的 Actor 模型models.py如下所示:
class Actor(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name = 'peactor')
# lots of other fields and some methods here
Run Code Online (Sandbox Code Playgroud)
在我的课程中admin.py,我有以下课程:
class ActorAdmin(admin.ModelAdmin):
# some defines for list_display, actions etc here
form = ActorForm
Run Code Online (Sandbox Code Playgroud)
我之前没有使用特殊的表单(只是依赖于 Django 默认为 ModelAdmin 提供的基本 ModelForm),但我需要它来解决以下问题。所以,最后,我的forms.py我有:
class ActorForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(ActorForm, self).__init__(*args, **kwargs)
#only provide users that are not already linked to an actor, plus the user that was already chosen for this Actor
self.fields['user'].queryset = User.objects.filter(Q(peactor__isnull=True)|Q(peactor=self.instance))
Run Code Online (Sandbox Code Playgroud)
所以这里我做了一个ActorForm并覆盖了该__init__方法。
self.fields['user'].queryset =
Run Code Online (Sandbox Code Playgroud)
设置用户表单字段要使用的查询集。默认情况下,此表单字段是 模型上 OneToOneField(或foreignkey)的ModelChoiceField 。
Q(peactor__isnull=True)|Q(peactor=self.instance)
Run Code Online (Sandbox Code Playgroud)
Q 代表Q 对象,有助于处理“复杂”查询,例如or语句。
所以这个查询说:其中peactor未设置或其中peactor与已为此演员选择的相同
peactor是related_name演员的。这样,您不仅可以获得可用的用户,还可以获得不可用的用户,因为它已经链接到您当前正在编辑的对象。
我希望这可以帮助有同样问题的人。:-)