0

I was using the q&a at Get Primary Key after Saving a ModelForm in Django.

It's exactly on point with what I need to do.

I have the following model:

class meetingEvent(models.Model):
    '''
    A meeting event
    '''

    name = models.CharField(max_length=64, help_text="a name for this meeting")
    account_number = models.ForeignKey(account)
    meeting_type = models.ForeignKey(meetingType)
    meeting_group = models.ForeignKey(meetingGroup)
    start_time = models.DateTimeField(help_text="start time for this event")
    end_time = models.DateTimeField(help_text="end time for this event")
    created_time = models.DateTimeField(auto_now_add=True)
    listed_products = models.ForeignKey(product)
    additonal_notes = models.TextField(help_text="additional notes for this meeting")

    def __unicode__(self):
        return self.name

I have the following form:

class meetingEventForm(forms.ModelForm):
    """
    to create a new meeting event.
    """
    portal_user = forms.CharField(help_text="username to access portal data")
    portal_pass = forms.CharField(widget=forms.PasswordInput, help_text="password to add access portal data")

    def save(self, commit=True):

        super(meetingEventForm, self).save(commit=commit)

    class Meta:
        model = meetingEvent

I have the following view:

def meeting_event(request):

    if request.method == 'POST':
        form = meetingEventForm(request.POST)
        if form.is_valid():
            new_agenda=form.save()

            return HttpResponseRedirect(reverse('agenda_detail', args=(new_agenda.pk,)))

    else:
        form = meetingEventForm()
        return render_to_response('agendas/event.html',{'form':form,}, context_instance=RequestContext(request))

I've confirmed that this makes it into the database cleanly. However, I get the following error:

Traceback:
File "/usr/lib/python2.6/site-packages/Django-1.5.2-py2.6.egg/django/core/handlers/base.py" in get_response
  115.                         response = callback(request, *callback_args, **callback_kwargs)
File "/usr/lib/python2.6/site-packages/Django-1.5.2-py2.6.egg/django/contrib/auth/decorators.py" in _wrapped_view
  25.                 return view_func(request, *args, **kwargs)
File "/var/www/html/tamtools/agendas/views.py" in meeting_event
  44.             return HttpResponseRedirect(reverse('agenda_detail', args=(new_agenda.pk,)))

Exception Type: AttributeError at /agendas/add/
Exception Value: 'NoneType' object has no attribute 'pk'

Has something changed in Django 1.5 that I don't know about? new_agenda should be a meetingEventForm type, shouldn't it?

4

2 回答 2

2

您覆盖了模型表单中的保存方法,但您忘记了返回模型。

return super( ....
于 2013-09-14T09:47:59.047 回答
1

您不需要重写 ModeForm 保存方法,因为您没有对它做任何特别的事情。您的 ModelForm 应如下所示:

class MeetingEventForm(forms.ModelForm):
    """
    to create a new meeting event.
    """
    class Meta:
        model = meetingEvent

我还更改了类名以符合 Python样式指南

表单中还有两个与模型无关的额外字段。可能有两个原因 - 第一个,您需要将这些字段保存在另一个模型中,或者第二个选项是您希望某人在添加新事件之前对其进行授权。

由于第二个似乎更合理,请从您的角度限制对表单的访问:

from django.contrib.auth.decorators import login_required
from django.shorcuts import render, redirect

@login_required()
def meeting_event(request):
    form = MeetingEventForm(request.POST or {})
    context = {'form': form}

    if request.method == 'POST':
        if form.is_valid():
            new_agenda = form.save()
            return redirect('agenda_detail', args=(new_agenda.pk,))
        else:
            return render(request, 'agendas/event.html', context)
    else:
        return render(request, 'agendas/event.html', context)

由于这是一项常见任务,并且您使用的是 django 1.5,为什么不使用基于通用类的视图

您的代码将减少,您不必担心平凡的细节:

首先,在您的 中views.py,创建一个从泛型继承的类,该类CreateView用于显示模型的模型表单,让用户填写并保存详细信息:

from django.views.generic.edit import CreateView

class CreateMeetingRequest(CreateView):
    template_name = 'agendas/event.html'
    model = meetingRequest

现在,要将视图映射到 url,我们将其添加到urls.py. 由于我们还希望用户在添加会议请求之前先登录 -login_required装饰器会为我们处理这些。它将检查用户是否登录 - 如果没有,将用户重定向到登录表单,一旦他们登录,将他们重定向回表单:

from django.contrib.auth.decorators import login_required

from .views import CreateMeetingRequest

urlpatterns = patterns('',
    # your other views
    url(r'meeting-request/add/$',
        login_required(CreateMeetingRequest.as_view()), name='add-meeting-req'),
)

最后,一旦表单成功,我们需要告诉视图去哪里。CreateView将检查模型是否有get_absolute_url方法,并调用它。所以在你的models.py

from django.core.urlresolvers import reverse

class meetingRequest(models.Model):

    # your normal fields

    def get_absolute_url(self):
       return reverse('agenda_detail', args=(self.pk,))
于 2013-09-14T10:13:56.423 回答