基于Django类的通用视图:根据上下文将字段设置为初始值

时间:2013-06-28 09:32:30

标签: python django django-views django-generic-views

我在Django 1.5应用程序中有一组相关模型:Events EventSessionsEventSessionRegistrations属于EventSessions

我正努力为面向用户的注册表单创建基于类的通用视图,用户注册该表单以参加EventSession。具体来说,问题在于排除在表单中呈现EventSession注册的字段,同时仍然根据上下文和/或URL设置该值。

我首先尝试通过用例解释:

  1. 用户转到'/events/foo/bar',其中fooEventbarEventSession
  2. 在此网址上,有一个注册EventSession的链接,指向'/events/foo/bar/register/'。显示EventSessionRegistration模型的表单,但未在UI中选择EventSession,因为该信息已经"设置"通过网址。
  3. 成功提交表单后,用户将被重定向到静态"感谢" -page。
  4. 为了实现这一点,我有以下视图代码(排除了许多其他导入等):

    from django.views.generic.edit import CreateView
    
    class RegistrationCreate(CreateView):
        form_class = SessionRegistrationForm
        success_url = '/thanks/'
        template_name = 'events/registration_create.html'
    
        def get_context_data(self, *args, **kwargs):
            """Set the context of which Event, and which EventSession.
               Return 404 if either Event or EventSession is not public."""
            context = super(RegistrationCreate, self).get_context_data(**kwargs)
            s = get_object_or_404(
                EventSession,
                event__slug=self.kwargs['event_slug'],
                event__is_public=True,
                slug=self.kwargs['session_slug'],
                is_public=True)
            context['session'] = s
            context['event'] = s.event
            return context
    

    此视图的网址格式(包含在基础urls.py中):

    url(r'^(?P<event_slug>[\w-]+)/(?P<session_slug>[\w-]+)/register/$',
        RegistrationCreate.as_view(), name="event_session_registration"),
    

    在ModelForm中,我尝试在EventSessionRegistration字段(指向session)上转换ForeignKey EventSession以显示HiddenInput() - 窗口小部件:

    class SessionRegistrationForm(forms.ModelForm):
    
        class Meta:
            model = EventSessionRegistration
            widgets = {
                'session': HiddenInput()
            }
    

    但我仍然不知道如何将该字段的初始值设置为我在'session'中设置的get_context_data值的ID。我已尝试在self.initial = {'session': s.id}内设置get_context_data,但我猜测initial属性已用于构建表单。

    有关实现这一目标的最佳方法的任何想法?我错过了什么?

1 个答案:

答案 0 :(得分:2)

是的,我找到this question,它处理同样的问题。 我最终在视图中使用了以下重写的post-function,并在隐藏字段中手动输出模板中的会话ID:

def post(self, request, *args, **kwargs):
    self.object = None
    evt_session = get_object_or_404(
        EventSession, pk=int(self.request.POST['session']))
    form_class = self.get_form_class()
    form = self.get_form(form_class)

    form.instance.session = evt_session

    if form.is_valid():
        return self.form_valid(form)
    else:
        return self.form_invalid(form)

另外,我找到ccbv.co.uk,这是查找CBV中所有方法和属性的一个很好的资源:s,它提供了如何构建覆盖的指导。