gpt4 book ai didi

将 ManyToManyField 渲染为 Textarea 时,Django "Enter a list of values"表单错误

转载 作者:行者123 更新时间:2023-12-04 03:46:12 25 4
gpt4 key购买 nike

我正在尝试学习 Django,但遇到了一些令人困惑的问题。我目前在使用表单创建电影时遇到问题。表单的想法是为用户提供他想要填写的任何字段。用户填写的任何字段都将在其各自的 sql 表中更新(空字段将被忽略)。但是,当我提交表单时,表单不断给我错误“输入值列表”。为了解决这个问题,我认为将表单中的数据填充到一个列表中,然后返回该列表可以解决这个问题。

第一个想法是覆盖 clean()在我的 ModelForm 中。但是,由于表单失败,is_valid()查看我的观点,cleaned_data clean() 中的变量不包含任何东西。接下来,我尝试覆盖 to_python() .然而,to_python()好像不叫

如果我把 __metaclass__ = models.SubfieldBase在相应的模型中,我收到运行时错误

"TypeError: Error when calling the metaclass bases metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases"



我的方法似乎不起作用。我不知道如何解决“输入值列表”错误!有什么建议吗?

这是相关代码(更新):
models.py

""" Idea:
A movie consists of many equipments, actors, and lighting techniques. It also has a rank for the particular movie, as well as a title.

A Theater consists of many movies.

A nation consists of many theaters.
"""

from django.db import models
from django.contrib.auth.models import User

class EquipmentModel(models.Model):
equip = models.CharField(max_length=20)
# user = models.ForeignKey(User)

class ActorModel(models.Model):
actor = models.CharField(max_length=20)
# user = models.ForeignKey(User)

class LightModel(models.Model):
light = models.CharField(max_length=20)
# user = models.ForeignKey(User)

class MovieModel(models.Model):
# __metaclass__ = models.SubfieldBase
rank = models.DecimalField(max_digits=5000, decimal_places=3)
title = models.CharField(max_length=20)

equipments = models.ManyToManyField(EquipmentModel, blank=True, null=True)
actors = models.ManyToManyField(ActorModel, blank=True, null=True)
lights = models.ManyToManyField(LightModel, blank=True, null=True)

class TheaterModel(models.Model):
movies = models.ForeignKey(MovieModel)

class NationModel(models.Model):
theaters = models.ForeignKey(TheaterModel)

=====================================
forms.py

"""
These Modelforms tie in the models from models.py

Users will be able to write to any of the fields in MovieModel when creating a movie.
Users may leave any field blank (empty fields should be ignored, ie: no updates to database).
"""

from django import forms
from models import MovieModel
from django.forms.widgets import Textarea

class MovieModelForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(MovieModelForm, self).__init__(*args, **kwargs)
self.fields["actors"].widget = Textarea()
self.fields["equipments"].widget = Textarea()
self.fields["lights"].widget = Textarea()

def clean_actors(self):
data = self.cleaned_data.get('actors')
print 'cleaning actors'
return [data]


class Meta:
model = MovieModel

=============================================
views.py

""" This will display the form used to create a MovieModel """

from django.shortcuts import render_to_response
from django.template import RequestContext
from forms import MovieModelForm

def add_movie(request):
if request.method == "POST":
form = MovieModelForm(request.POST)

if form.is_valid():
new_moviemodel = form.save()
return HttpResponseRedirect('/data/')

else:
form = MovieModelForm()

return render_to_response('add_movie_form.html', {form:form,}, context_instance=RequestContext(request))

最佳答案

可能的问题是文本区域中提供的值列表无法规范化为模型列表。

ModelMultipleChoiceField documentation .

该字段需要一个有效 ID 列表,但可能正在接收一个文本值列表,django 无法将其转换为实际模型实例。 to_python将在表单字段内失败,而不是在表单本身内失败。因此,这些值甚至永远不会达到形式。

使用内置的 ModelMultipleChoiceField 有什么问题吗?它将提供最简单的方法,但需要您的用户扫描可用 Actor 的列表(我在这里使用 Actor 字段作为示例)。

在我展示我将如何尝试做你想做的事的例子之前,我必须问;您想如何处理已输入但数据库中尚不存在的 Actor ?如果它们存在,您可以创建它们,也可以失败。您需要对此做出决定。

# only showing the actor example, you can use something like this for other fields too

class MovieModelForm(forms.ModelForm):
actors_list = fields.CharField(required=False, widget=forms.Textarea())

class Meta:
model = MovieModel
exclude = ('actors',)

def clean_actors_list(self):
data = self.cleaned_data
actors_list = data.get('actors_list', None)
if actors_list is not None:
for actor_name in actors_list.split(','):
try:
actor = Actor.objects.get(actor=actor_name)
except Actor.DoesNotExist:
if FAIL_ON_NOT_EXIST: # decide if you want this behaviour or to create it
raise forms.ValidationError('Actor %s does not exist' % actor_name)
else: # create it if it doesnt exist
Actor(actor=actor_name).save()
return actors_list

def save(self, commit=True):
mminstance = super(MovieModelForm, self).save(commit=commit)
actors_list = self.cleaned_data.get('actors_list', None)
if actors_list is not None:
for actor_name in actors_list.split(","):
actor = Actor.objects.get(actor=actor_name)
mminstance.actors.add(actor)

mminstance.save()
return mminstance

以上都是未经测试的代码,但是如果您真的想为 ModelMultipleChoiceField 使用 Textarea,那么接近此的代码应该可以工作。如果您确实沿着这条路线走,并且发现我上面的代码中有错误,请编辑我的答案,或提供评论以便我可以。祝你好运。

编辑:

另一种选择是创建一个字段,该字段理解逗号分隔的值列表,但其行为方式与 ModelMultipleChoiceField 类似。查看 ModelMultipleChoiceField 的源代码,它继承自 ModelChoiceField,它允许您定义模型上的哪个值用于规范化。
## removed code because it's no longer relevant. See Last Edit ##

编辑:

哇,我真的应该检查 django trac 看看这是否已经修复。这是。见 following ticket信息。本质上,他们做了和我一样的事情。他们让 ModelMutipleChoiceField 尊重 to_field_name争论。 这仅适用于 django 1.3!

问题是,常规的 ModelMultipleChoiceField 将看到逗号分隔的字符串,并失败,因为它不是列表或元组。因此,我们的工作变得有点困难,因为在常规的 clean 方法可以运行之前,我们必须将字符串更改为列表或元组。
class ModelCommaSeparatedChoiceField(ModelMultipleChoiceField):
widget = Textarea
def clean(self, value):
if value is not None:
value = [item.strip() for item in value.split(",")] # remove padding
return super(ModelCommaSeparatedChoiceField, self).clean(value)

所以,现在你的表单应该是这样的:
class MovieModelForm(forms.ModelForm):
actors = ModelCommaSeparatedChoiceField(
required=False,
queryset=Actor.objects.filter(),
to_field_name='actor')
equipments = ModelCommaSeparatedChoiceField(
required=False,
queryset=Equipment.objects.filter(),
to_field_name='equip')
lights = ModelCommaSeparatedChoiceField(
required=False,
queryset=Light.objects.filter(),
to_field_name='light')

class Meta:
model = MovieModel

关于将 ManyToManyField 渲染为 Textarea 时,Django "Enter a list of values"表单错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5608576/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com