Django 'QuerySet' 对象没有使用 modelform 的属性'split'
Posted
技术标签:
【中文标题】Django \'QuerySet\' 对象没有使用 modelform 的属性\'split\'【英文标题】:Django 'QuerySet' object has no attribute 'split' using modelformDjango 'QuerySet' 对象没有使用 modelform 的属性'split' 【发布时间】:2012-08-21 02:18:04 【问题描述】:我无法让我的视图更新多对多字段。提交表单后返回。
Traceback:
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py" in get_response
111. response = callback(request, *callback_args, **callback_kwargs)
File "/home/footbook/Ubuntu One/webapps/fb/poc/../poc/activity/views.py" in activity_save_page
44. group_names = form.cleaned_data['groups'].split()
Exception Type: AttributeError at /activity_save/
Exception Value: 'QuerySet' object has no attribute 'split'
这里是文件。 模型.py
class Group (models.Model):
group_nm = models.CharField(max_length=64)
group_desc = models.CharField(max_length=250)
created = models.DateTimeField(auto_now_add=True)
active_yn = models.BooleanField(default=True)
def __unicode__(self):
return self.group_nm
class Activity(models.Model):
activity_nm = models.CharField(max_length=60)
activity_desc = models.CharField(max_length=250)
startdt = models.DateField()
enddt = models.DateField()
crdt = models.DateTimeField(auto_now_add=True,editable=False)
groups = models.ManyToManyField(Group)
upddt = models.DateTimeField(editable=False)
def save(self, *args, **kwargs):
if not self.id:
self.crdt = datetime.date.today()
self.upddt = datetime.datetime.today()
super(Activity, self).save(*args, **kwargs)
def __unicode__(self):
return self.name
forms.py
def make_custom_datefield(f):
formfield = f.formfield()
if isinstance(f, models.DateField):
formfield.widget.format = '%m/%d/%Y'
formfield.widget.attrs.update('class':'datePicker', 'readonly':'true')
return formfield
class ActivitySaveForm(forms.ModelForm):
formfield_callback = make_custom_datefield
def __init__(self, *args, **kwargs):
super(ActivitySaveForm, self).__init__(*args, **kwargs)
self.fields['activity_nm'].label = "Activity Name"
self.fields['activity_desc'].label = "Describe It"
self.fields['startdt'].label = "Start Date"
self.fields['enddt'].label = "End Date"
self.fields['groups'].label ="Group"
class Meta:
model = Activity
views.py
def activity_save_page(request):
if request.method == 'POST':
form = ActivitySaveForm(request.POST)
if form.is_valid():
act, created = Activity.objects.get_or_create(
activity_nm = form.cleaned_data['activity_nm']
)
act.activity_desc = form.cleaned_data['activity_desc']
if not created:
act.group_set.clear()
group_names = form.cleaned_data['groups'].split()
for group_name in group_names:
group, dummy = Group.objects.get_or_create(group_nm=group_name)
act.group_set.add(group)
act.save()
return HttpResponseRedirect('/activity/')
else:
form = ActivitySaveForm()
variables = RequestContext(request,
'form': form
)
return render_to_response('activity_save.html', variables)
我认为如果我不使用模型表单它会起作用,但我需要它来实现this datepicker. 因为它是一个多对多字段,我想在它们输入数据库时将它们拆分,但我的查询集失败了。我试过用很多不同的方式改变它,但我被卡住了。我见过很多类似的问题,但它们要么有外键,要么没有模型形式。
谢谢。
编辑: activity_save.html
% extends "base.html" %
% block title %Save Activity% endblock %
% block head %Save Activty% endblock %
<input class="datePicker" readonly="true" type="text" id="id_startdt" />
<input class="datePicker" readonly="true" type="text" id="id_enddt" />
% block content %
<form action="% url activity.views.activity_save_page act_id%" method="post">% csrf_token %
form.as_p
<input type="submit" value="save it" />
</form>
% endblock %
【问题讨论】:
【参考方案1】:正如错误描述的那样:QuerySet
没有split
方法。你不能打电话给my_qs.split()
。
form.cleaned_data['groups']
返回清理数据;它已经为您处理了字符串到python对象的形式转换,在ManyToManyField
的情况下,最终由python中的QuerySet
表示。
日期字段返回日期对象,IntegerField 一个整数,CharFields 一个字符串,等等。通过表单清理以相同的方式。
如果您想要group_names
的列表,您需要显式地遍历QuerySet
中的对象并提取它们的group_nm
属性。
group_names = [x.group_nm for x in form.cleaned_data['groups']]
【讨论】:
感谢您帮助澄清查询集。但是,一旦我使用for
循环检索,我仍然不知道如何使用活动清除和保存 m2m 组查询集。感谢您的帮助。
清除并保存m2m?听起来像是一个新问题 - 您可能想重新提出它并明确您在寻找什么。要“清除”一个 m2m,也就是删除所有关联,您可以调用 my_m2m_field.clear()
。要添加它们,my_m2m_field.add(*[1, 2, 3, 4])
谢谢宇治。如果我无法解决它,我将重新发布一个更清晰的问题。为信息 +1。
没问题,有什么问题请告诉我!
用你的方法解决了。再次感谢!【参考方案2】:
我不确定您是否需要按照您的观点执行所有这些操作。您可以直接将表单保存在视图中,而无需手动创建对象并对其进行操作。
另外,您需要获取活动的 id,以便您可以更新现有活动实例。
更新urls.py
以使这些网址具有act_id
:
url(r'^activity_app/save/(?P<act_id>\d+)/$', 'activity_app.views.activity_save_page'),
url(r'^activity_app/save/$', 'activity_app.views.activity_save_page'),
我会将视图更改为:
def activity_save_page(request, act_id=None):
act_inst = None
try:
if act_id:
act_inst = Activity.objects.get(id=act_id)
except Exception:
pass
if request.method == 'POST':
form = ActivitySaveForm(request.POST, instance=act_inst)
if form.is_valid():
return HttpResponseRedirect('/activity/')
else:
form = ActivitySaveForm(instance=act_inst)
variables = RequestContext(request,
'form': form
)
return render_to_response('activity_save.html', variables)
【讨论】:
感谢您的详细回复。不过,我用这种方法得到了一个不同的错误:local variable 'act_inst' referenced before assignment
。当它不是 POST 时,错误引用了表单创建。为什么,当最初创建表单时,我想让表单期望设置变量,因为没有发布数据?再次感谢!
@jabs 哦,是的,当 act_id
是 None
act_inst
时将不会被定义。请检查更新的答案。
这一次,我收到了Caught NoReverseMatch
错误。这是我在模板中的调用:<form action="% url activity activity_save_page.act_id %" method="post">% csrf_token %
我尝试以多种不同的方式调用该 act_id 值,但最终都会出现相同的错误。
另外,当我尝试反向查找 reverse('poc.views.activity_save_page')
时,我得到了同样的错误:File "<console>", line 1, in <module> File "/usr/local/lib/python2.7/dist-packages/django/core/urlresolvers.py", line 391, in reverse *args, **kwargs))) File "/usr/local/lib/python2.7/dist-packages/django/core/urlresolvers.py", line 337, in reverse "arguments '%s' not found." % (lookup_view_s, args, kwargs)) NoReverseMatch: Reverse for 'poc.views.activity_save_page' with arguments '()' and keyword arguments '' not found.
不确定我是否做对了......
当我删除模板标签% url activity.views.activity_save_page %
中对变量的任何引用并调用页面时,视图正确形成并接受输入,但不会更新或插入数据库。如何找出视图失败的地方?以上是关于Django 'QuerySet' 对象没有使用 modelform 的属性'split'的主要内容,如果未能解决你的问题,请参考以下文章
Django QuerySet 对象没有属性'objects
Django - 如何将 QuerySet 转换为 Q 对象?
QuerySet 对象在 Django Rest Framework 上没有属性“用户”