Django 表单 'list' 对象没有属性 'iterator'
Django Form 'list' object has no attribute 'iterator'
我是 django 的新手,我正在尝试根据此处的答案连接来自不同模型的不同查询集:
当我试图在我的管理员中查看它时,我总是收到这个错误。
'list' object has no attribute 'iterator'
我在 forms.py
中调用它
from django import forms
from itertools import chain
from content.models import Article, Tutorial
class DashboardChoiceForm(forms.Modelform):
dashboard_select = forms.ModelChoiceField(queryset=None)
def __init__(self, *args, **kwargs):
super(DashboardChoiceForm, self).__init__(*args, **kwargs)
article_list = Article.objects.all()
tutorial_list = Tutorial.objects.all()
self.fields['dashboard_select'].queryset = list(chain(article_list, tutorial_list))
我将它包含在我的管理页面中,如下所示:
from django.contrib import admin
from .models import *
from .forms import *
class RowSingleAdmin(admin.ModelAdmin):
model = RowSingle
form = DashboardChoiceForm
我想做的是在 RowSingle 管理员上创建一个下拉列表,这样用户就可以 select 一个内容项(文章或教程)显示在该行中。
这条线行不通:
self.fields['dashboard_select'].queryset = list(chain(article_list, tutorial_list))
问题不是出在右边,而是出在左边。 ModelChoiceField
期望 queryset
是一个实际的查询集,而不是列表。
如果你想提供一个列表,你应该使用另一种字段类型,即ChoiceField
。然后您将需要分配选项。它们必须是一个二元组列表,其中第一项是实际值,第二项是显示的文本。
这变得有点棘手,因为实际值必须是字符串,或者可以转换为字符串的东西。例如,我们可以对文章做 "article_<pk>",对教程做 "tutorial_<pk>"。
choices = chain(
('article_%d' % obj.pk, str(obj)) for obj in article_list),
('tutorial_%d' % obj.pk, str(obj)) for obj in tutorial_list),
)
self.fields['dashboard_select'].choices = choices
您可以将 str(obj)
替换为向用户显示对象的任何合理方式。
然后当您的表单通过验证时,您将获得您应该解析回来的值:
from django.core.exceptions import ObjectDoesNotExist, ValidationError
# on your form class
def clean_dashboard_select(self):
data = self.cleaned_data['dashboard_select'] # will be, eg: "article_42"
try:
typename, value = data.split('_')
pk = int(value)
except ValueError:
raise ValidationError('cannot understand %s' % data)
try:
if typename == 'article':
return Article.objects.get(pk=pk)
if typename == 'tutorial':
return Tutorial.objects.get(pk=pk)
except ObjectDoesNotExist:
raise ValidationError('No %s with pk %d' % (typename, pk))
raise ValidationError('Never heard of type %s' % typename)
编辑(来自评论)— 添加分区组,更改选项如下:
choices = (
('Articles', tuple(('article_%d' % obj.pk, str(obj)) for obj in article_list)),
('Tutorials', tuple(('tutorial_%d' % obj.pk, str(obj)) for obj in tutorial_list)),
)
我是 django 的新手,我正在尝试根据此处的答案连接来自不同模型的不同查询集:
当我试图在我的管理员中查看它时,我总是收到这个错误。
'list' object has no attribute 'iterator'
我在 forms.py
中调用它 from django import forms
from itertools import chain
from content.models import Article, Tutorial
class DashboardChoiceForm(forms.Modelform):
dashboard_select = forms.ModelChoiceField(queryset=None)
def __init__(self, *args, **kwargs):
super(DashboardChoiceForm, self).__init__(*args, **kwargs)
article_list = Article.objects.all()
tutorial_list = Tutorial.objects.all()
self.fields['dashboard_select'].queryset = list(chain(article_list, tutorial_list))
我将它包含在我的管理页面中,如下所示:
from django.contrib import admin
from .models import *
from .forms import *
class RowSingleAdmin(admin.ModelAdmin):
model = RowSingle
form = DashboardChoiceForm
我想做的是在 RowSingle 管理员上创建一个下拉列表,这样用户就可以 select 一个内容项(文章或教程)显示在该行中。
这条线行不通:
self.fields['dashboard_select'].queryset = list(chain(article_list, tutorial_list))
问题不是出在右边,而是出在左边。 ModelChoiceField
期望 queryset
是一个实际的查询集,而不是列表。
如果你想提供一个列表,你应该使用另一种字段类型,即ChoiceField
。然后您将需要分配选项。它们必须是一个二元组列表,其中第一项是实际值,第二项是显示的文本。
这变得有点棘手,因为实际值必须是字符串,或者可以转换为字符串的东西。例如,我们可以对文章做 "article_<pk>",对教程做 "tutorial_<pk>"。
choices = chain(
('article_%d' % obj.pk, str(obj)) for obj in article_list),
('tutorial_%d' % obj.pk, str(obj)) for obj in tutorial_list),
)
self.fields['dashboard_select'].choices = choices
您可以将 str(obj)
替换为向用户显示对象的任何合理方式。
然后当您的表单通过验证时,您将获得您应该解析回来的值:
from django.core.exceptions import ObjectDoesNotExist, ValidationError
# on your form class
def clean_dashboard_select(self):
data = self.cleaned_data['dashboard_select'] # will be, eg: "article_42"
try:
typename, value = data.split('_')
pk = int(value)
except ValueError:
raise ValidationError('cannot understand %s' % data)
try:
if typename == 'article':
return Article.objects.get(pk=pk)
if typename == 'tutorial':
return Tutorial.objects.get(pk=pk)
except ObjectDoesNotExist:
raise ValidationError('No %s with pk %d' % (typename, pk))
raise ValidationError('Never heard of type %s' % typename)
编辑(来自评论)— 添加分区组,更改选项如下:
choices = (
('Articles', tuple(('article_%d' % obj.pk, str(obj)) for obj in article_list)),
('Tutorials', tuple(('tutorial_%d' % obj.pk, str(obj)) for obj in tutorial_list)),
)