首页 > 解决方案 > TypeError:“DeferredAttribute”对象不可迭代

问题描述

在我的 models.py 中,我有以下类:

class AvailabilityTypes():
    STUDYING = 'STUDYING'
    WORKING = 'WORKING'
    SEARCHING = 'SEARCHING'
    FREELANCER = 'FREELANCER'

    types = (
        (STUDYING, 'Estudando'),
        (WORKING, 'Trabalhando'),
        (SEARCHING, 'Procurando por emprego'),
        (FREELANCER, 'Freelancer')
    )

    def get_types(self):
        return self.types.all()

我想在 Django 表单中显示这些选项。在我的 forms.py 文件中,我有以下代码:

from django import forms
from .models import AvailabilityTypes

[...]

availability = forms.CharField(
        widget=forms.ChoiceField(
            choices=(AvailabilityTypes.types)
        )
    )

但我得到了错误TypeError: 'DeferredAttribute' object is not iterable。我究竟做错了什么?另外,如果我尝试使用:

availability = forms.CharField(
        widget=forms.ChoiceField(
            choices=(AvailabilityTypes.get_types())
        )
    )

我得到错误TypeError: get_types() missing 1 required positional argument: 'self'.

我是 Django 和 Python 的新手,我可以使用一些光。谢谢你。

标签: pythondjango

解决方案


解决方案 1. 修复您当前的代码

首先修复您的方法get_types()

class AvailabilityTypes():
...
# Above this Same as your code

def get_types(self):
    return self.types  # You need to return just types, it is a tuple, it doesn't has an attribute all(). In Django we usually use all() in querysets.

现在修复表格:

from django import forms
from .models import AvailabilityTypes

at_obj = AvailabilityTypes()  # Create an object of class AvailabilityTypes

[...]  # Guessing form class starts here

availability = forms.CharField(
    widget=forms.ChoiceField(
        # choices=AvailabilityTypes.get_types()  # You can't call a class's method on that class, you call it on that class's object
        choices=(at_obj.get_types())  # Call the method on object of the class not class itself
    )
)

Sol 2. 不要创建不必要的类

在 models.py 中不需要创建一个类来保存类型。你可以这样做:

...
# All your imports go above this
# These four variables are pointless in my opinion, but I will leave them be
STUDYING = 'STUDYING'
WORKING = 'WORKING'
SEARCHING = 'SEARCHING'
FREELANCER = 'FREELANCER'

# types is an constant so it should follow uppercase naming style
TYPES = (  
    (STUDYING, 'Estudando'),
    (WORKING, 'Trabalhando'),
    (SEARCHING, 'Procurando por emprego'),
    (FREELANCER, 'Freelancer')
)

# Create your models Here
...

现在在你的 forms.py 中:

...
from .models import TYPES  # Import the tuple from models

[...]

availability = forms.CharField(
    widget=forms.ChoiceField(choices=TYPES)  # Use the imported tuple directly here
)

Sol 3. 使用模型形式(最简单最简单)

在您的模型中:

from django.db import models

# types is an constant so it should follow uppercase naming style
TYPES = (  
    ('STUDYING', 'Estudando', ),
    ('WORKING', 'Trabalhando', ),
    ('SEARCHING', 'Procurando por emprego', ),
    ('FREELANCER', 'Freelancer', ),  # Unlike other languages your last element can have a trailing comma too, its optional but still do that. I has some advantages which I am not gonna explain here
)

# Create your models Here
class MyModel(models.Model):
    availability = models.CharField(max_length=63, choices=TYPES)
    # Other fields of your model
    ...

现在在你的 forms.py 中:

from django import forms
from .models import MyModel

class MyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel
        fields = ('availability', )  # add other fields of your models too in the tuple

就是这样。你完成了,在视图中使用你的表单。Django 将负责显示正确的选择、验证它们、显示相关的错误消息并将有效数据保存在数据库中。


推荐阅读