Django 'QuerySet' обект няма атрибут 'split' с помощта на modelform

Имам проблем с получаването на моя изглед за актуализиране на многотомани поле. Той връща това, след като формулярът бъде изпратен.

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'

Ето ги файловете. Models.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)

Мисля, че щеше да работи, ако не използвах modelform, но имам нужда от него, за да внедря този инструмент за избор на дати. Тъй като полето е много-много, искам да ги разделя, когато бъдат въведени в базата данни, но моят набор от заявки е неуспешен. Опитах да променя това по куп различни начини, но останах. Виждал съм много подобни въпроси, но те или имаха външни ключове, или нямаха моделна форма.

Благодаря.

РЕДАКТИРАНЕ: 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 %}

person jabs    schedule 26.08.2012    source източник


Отговори (2)


Точно както грешката описва: QuerySet няма split метод. Не можете да се обадите на my_qs.split().

form.cleaned_data['groups'] връща изчистени данни; той вече се е погрижил за преобразуването на формата от низ към обект на Python вместо вас, което в случай на ManyToManyField в крайна сметка е представено от QuerySet в python.

Поле за дата връща обекти за дата, IntegerField цяло число, CharFields низ и т.н. по същия начин чрез почистване на формуляр.

Ако искате списък от group_names, ще трябва изрично да преминете през обектите в QuerySet и да изтеглите техния атрибут group_nm.

            group_names = [x.group_nm for x in form.cleaned_data['groups']]
person Yuji 'Tomita' Tomita    schedule 26.08.2012
comment
Благодаря за помощта за изясняване на наборите от заявки. Но все още съм на загуба как да изчистя и запазя групата m2m queryset с дейността, след като извлека с for цикъла. Благодаря за вашата помощ. - person jabs; 27.08.2012
comment
Изчистване и запазване на m2m? Звучи като нов въпрос - може да искате да го зададете отново и да изясните какво търсите. За да изчистите m2m, т.е. да премахнете всички асоциации, трябва да извикате my_m2m_field.clear(). За да ги добавите, my_m2m_field.add(*[1, 2, 3, 4]) - person Yuji 'Tomita' Tomita; 27.08.2012
comment
Благодаря Юджи. Ако не мога да го разбера, ще публикувам отново с по-ясен въпрос. +1 за инфото. - person jabs; 28.08.2012
comment
Няма проблем, кажете ми, ако има нещо друго! - person Yuji 'Tomita' Tomita; 28.08.2012
comment
Реших го с помощта на вашия подход. Благодаря отново! - person jabs; 28.08.2012

Не съм сигурен, че трябва да правите всичко това според вас. Можете директно да запазите формуляра в изгледа, без да създавате ръчно обектите и да ги манипулирате.

Освен това трябва да получите идентификатора на активността, за да можете да актуализирате съществуващ екземпляр на дейност.

Актуализирайте urls.py, за да имате тези URL адреси, за да имате 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)
person Rohan    schedule 26.08.2012
comment
Благодаря за подробния отговор. Все пак получавам различна грешка с този подход: local variable 'act_inst' referenced before assignment. Грешката препраща към създаването на формуляр, когато не е POST. Защо, когато формулярът е създаден първоначално, бих искал формулярът да очаква променливата да бъде зададена, след като не са публикувани данни? Още веднъж благодаря! - person jabs; 27.08.2012
comment
@jabs о, да, когато act_id е None act_inst няма да се дефинира. Моля, проверете актуализирания отговор. - person Rohan; 27.08.2012
comment
Този път получих грешка Caught NoReverseMatch. Ето моето извикване в шаблона: <form action="{% url activity activity_save_page.act_id %}" method="post">{% csrf_token %} Опитах се да извикам тази стойност act_id по няколко различни начина, но всичко завършва с една и съща грешка. - person jabs; 28.08.2012
comment
Освен това, когато опитах обратно търсене 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. Не съм сигурен дали го направих правилно... - person jabs; 28.08.2012
comment
когато премахна всяка препратка към променливата в етикета на шаблона {% url activity.views.activity_save_page %} и просто извикам страницата, изгледът се формира правилно и приема въвеждане, но няма да се актуализира или вмъкне в базата данни. Как мога да разбера къде изгледът се проваля? - person jabs; 28.08.2012
comment
@jabs Опитайте {% url activity.views.activity_save_page act_id%} в шаблона. Имайте предвид, че трябва да предадете параметър act_id към вашия шаблон. - person Rohan; 28.08.2012
comment
за съжаление, това също връща грешката Caught NoReverseMatch. Опитах много различни обаждания, за да върна стойността на id, но все още не съм открил какво работи. - person jabs; 28.08.2012
comment
@jabs URL маркерът трябва да бъде {% url 'activity.views.activity_save_page' act_id %}, единични кавички около изгледа. Ако това не работи, може би трябва да зададете друг въпрос с подробности, специфични за тази грешка. - person Rohan; 28.08.2012
comment
За съжаление не успях да го накарам да работи. Благодаря, че го разгледахте и (+1), че ми показахте пример за това как директно да запазя формуляра, без да създавам обектите. - person jabs; 28.08.2012