【问题标题】:Model.ManyToManyField.all() gives AttributeError: 'ManyToManyDescriptor' object has no attribute 'all'Model.ManyToManyField.all() 给出 AttributeError: 'ManyToManyDescriptor' 对象没有属性 'all'
【发布时间】:2018-03-25 22:28:45
【问题描述】:

我正在使用 Django 2.0.2、Python 3.6.4 和 PyCharm 2017.3.3

模型:(在 models.py 中)

class Position(models.Model):
    title = models.CharField(max_length=50)
    gang = models.ForeignKey(Gang, on_delete=models.CASCADE)
    description = models.TextField(max_length=20000)

    def __str__(self):
        return str(self.title) + ', ' + str(self.gang)

class Application(models.Model):
    positions = models.ManyToManyField(Position)
    applicant = models.ForeignKey(User, on_delete=models.CASCADE)

class Ranking(models.Model):
    position = models.ForeignKey(Position, on_delete=models.CASCADE)
    applicant = models.ForeignKey(User, on_delete=models.CASCADE)
    rank = models.IntegerField(default=3,validators=[
            MaxValueValidator(3),
            MinValueValidator(1)
        ])

表单:(在 forms.py 中)

class RankingForm(forms.ModelForm):
    rank = forms.IntegerField(max_value=3, min_value=1)
    position = forms.ModelMultipleChoiceField(queryset=Application.positions.all())

    class Meta:
        model = Ranking
        exclude = ['applicant']
        fields = ('rank', 'position')

    def __init__(self, *args, **kwargs):
        super(RankingForm, self).__init__(*args, **kwargs)
        self.fields['rank'].widget.attrs.update({'class': 'form-control'})

我不断收到 RankingForm 中的 AttributeError 来自

"position = forms.ModelMultipleChoiceField(queryset=Application.positions.all())"

当我写作时

class Application(models.Model):
    ... 

    def __str__(self):
        return str(self.positions.all())

它在 django-admin 中显示为 QuerySet(适用于 forms.ModelMultipleChoiceField()),但写作

    class Application(models.Model):
    ... 

    def __str__(self):
        return str(Application.positions.all())

给我同样的错误:'ManyToManyDescriptor' 对象没有属性'all'

写作

    class RankingForm(forms.ModelForm):
        ...
        position = forms.ModelMultipleChoiceField(queryset=Position.objects.all())

有效,但这不是我希望该字段显示的内容。

我想使用来自特定应用程序的所有位置创建一个 ModelMultipleChoiceField(),但是这个错误一直在阻碍。似乎只引用一个模型是行不通的,但引用 self 呢?任何帮助是极大的赞赏! :)

顺便说一句,我还没有找到关于这个问题的任何好的文档,但this 似乎是 ManyToManyDescriptor 所在的 related_descriptors.py 的代码

【问题讨论】:

  • 您的问题令人困惑。你知道工作语法,使用 self,那你为什么要尝试使用其他版本?
  • 您需要一个应用程序的实例,并且不能使用未初始化的类的属性。
  • 您应该有 self.positions.all() 而不是 Application.positions.all() self 引用应用程序的一个实例。对于表单,应该在初始化时评估查询集而不是在类级别,即position = forms.ModelMultipleChoiceField(queryset=Positions.objects.none())
  • @DanielRoseman “其他版本”是什么意思?
  • @jackotonye 是的,我想引用应用程序实例,但是当我在 forms.py 中时该怎么做?

标签: python django attributeerror manytomanyfield django-2.0


【解决方案1】:

使用作为类的初始化实例的实例来评估关系。

应用程序的一个实例。

application = Application.objects.first()
application.positions.all()

初始化后更改表单查询集。

class RankingForm(forms.ModelForm):
    rank = forms.IntegerField(max_value=3, min_value=1)
    position = forms.ModelMultipleChoiceField(queryset=Positions.objects.none())

    class Meta:
        model = Ranking
        exclude = ['applicant']
        fields = ['rank', 'position']

    def __init__(self, *args, **kwargs):
        super(RankingForm, self).__init__(*args, **kwargs)
        self.fields['rank'].widget.attrs.update({'class': 'form-control'})  
        self.fields['position'].queryset = self.instance.positions.all()

【讨论】:

  • 谢谢!现在想来,我的问题真的只能归结为“如何制作模型实例”哈哈。
  • 但我确实需要为查看表单的特定用户创建一个模型实例。有什么帮助吗?
  • 实例在用户保存表单后创建,编辑视图引用保存的表单实例。
【解决方案2】:

您可以使用instance 属性访问ModelForm 对象正在使用的模型的当前实例。然后您可以使用它在__init__ 中创建正确的查询集:

class RankingForm(forms.ModelForm):
    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['rank'].widget.attrs.update({'class': 'form-control'})
        self.fields['position'].queryset = self.instance.positions.all()

【讨论】:

    猜你喜欢
    • 2017-06-16
    • 1970-01-01
    • 2019-01-11
    • 2021-07-06
    • 1970-01-01
    • 2021-10-09
    • 1970-01-01
    • 1970-01-01
    • 2012-12-01
    相关资源
    最近更新 更多