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_idNone act_inst 时将不会被定义。请检查更新的答案。 这一次,我收到了Caught NoReverseMatch 错误。这是我在模板中的调用:&lt;form action="% url activity activity_save_page.act_id %" method="post"&gt;% csrf_token % 我尝试以多种不同的方式调用该 act_id 值,但最终都会出现相同的错误。 另外,当我尝试反向查找 reverse('poc.views.activity_save_page') 时,我得到了同样的错误:File "&lt;console&gt;", line 1, in &lt;module&gt; 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 上没有属性“用户”

Django Queryset 过滤器检查相关对象是不是存在

Django QuerySet OR 语句 [重复]

django的queryset和objects对象