Model.ManyToManyField.all() gives AttributeError: 'ManyToManyDescriptor' object has no attribute 'all'

北战南征 提交于 2020-01-15 11:49:26

问题


I'm using Django 2.0.2, Python 3.6.4 and PyCharm 2017.3.3

Models: (in 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)
        ])

Form: (in 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'})

I keep getting the AttributeError in RankingForm from

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

When i write

class Application(models.Model):
    ... 

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

it shows in django-admin as a QuerySet (which works for forms.ModelMultipleChoiceField()), but writing

    class Application(models.Model):
    ... 

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

gives me the same error: 'ManyToManyDescriptor' object has no attribute 'all'

Writing

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

works, but this is not what i want the field to display.

I want to make a ModelMultipleChoiceField() with all the positions from a specific application, but this error keeps getting in the way. It seems that just referencing a model doesn't work, but referencing self does?? Any help is greatly appreciated! :)

Btw, I haven't found any good documentation on this problem, but this seems to be the code for related_descriptors.py where ManyToManyDescriptor is located


回答1:


Evaluating relationships are done with an instance that is an initialized instance of the class.

An instance of the Application.

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

Change the form queryset after initialization.

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:


You can access the current instance of your model that the ModelForm object is working with using the instance attribute. You can then use it to create the correct queryset in __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()


来源:https://stackoverflow.com/questions/49481650/model-manytomanyfield-all-gives-attributeerror-manytomanydescriptor-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!