2014-01-27 25 views
1

我有一个Workshop Django应用程序。每个Workshop可以有多个与会者通过相关的WorkshopAttendee模型(简化如下)。我使用Django的ModelForm在基于类的视图,并在forms.py我使用crispy-formsDjango ModelForms:在表单中嵌入FK相关字段

models.py(相关部分)

class Workshop(models.Model): 
    title = models.CharField(max_length=100) 
    information = models.TextField() 
    location = models.TextField() 

class WorkshopAttendee(models.Model): 
    workshop = models.ForeignKey(Workshop) 
    first_name = models.CharField(max_length=100) 
    last_name = models.CharField(max_length=100) 

views.py(相关部分)

from django.views.generic.edit import FormView 
from workshop.forms import WorkshopAttendeeForm 

class WorkshopAttendeeFormView(FormView): 

    def form_valid(self, form): 
     # Clean the data 
     form_data = form.cleaned_data 
     form.save(commit=False) 
     return super(WorkshopAttendeeFormView, self).form_valid(form) 

forms.py

from django.forms import ModelForm 
from workshop.models import WorkshopAttendee 
from crispy_forms.helper import FormHelper 
from crispy_forms.layout import Layout, HTML, Field, \ 
    Fieldset, Button, Hidden, Submit, Reset 
from crispy_forms.bootstrap import FormActions 

# Create the form class 
class WorkshopAttendeeForm(ModelForm): 
    def __init__(self, *args, **kwargs): 
     # Crispy form Layouts, Fieldsets, etc 
     super(WorkshopAttendeeForm, self).__init__(*args, **kwargs) 

    class Meta: 
     model = WorkshopAttendee 

urls.py(相关部分)

urlpatterns = patterns('', 
    url(r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<slug>[\w\-.]+)/(?P<action>[\w\-.]+)/$', 
     WorkshopAttendeeFormView.as_view(
      form_class=WorkshopAttendeeForm, 
      success_url="success/", 
      template_name='workshop/workshop_registration.html', 
     ), name='workshop-attendee-register' 
    ), 
    url(r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<slug>[\w\-.]+)/$', 
     WorkshopDetailView.as_view(
      context_object_name='workshop_detail', 
      queryset=Workshop.objects.select_related(), 
      template_name='workshop/workshop_detail.html', 
     ), name='workshop-detail' 
    ), 
) 

我的问题是,如何可以种子与workshop_id的形式(即FK关系)在一个隐藏的表单域?很明显,因为表格尚未提交,所以还没有FK关系。但在URL中我有kwargWorkshopslu 012。我可以在每个车间基础上将workshop_id作为Hidden()香脆形式字段进行硬编码,但这完全不合逻辑。有任何想法吗?我不认为我可以在urls.py的模型上使用select_related()prefetch_related()方法,所以也许我必须以某种方式将两种模型都以某种方式放入窗体视图中?

我不觉得这是一种边缘情况,我相信别人也有类似的应用程序工作流程。

在此先感谢。

UPDATE

经过进一步研究,似乎我能做到这一点,利用Django Formsets。不知道究竟如何......提示欢迎。

+1

你得到了slu,子,对吧?你为什么不在视图中使用它来保存任何东西之前获得PK?为什么你需要通过你的形式? – Thomas

+0

听起来不错。在我看来,究竟在哪里使用?我需要在表单中传递PK,所以我知道'WorkshopAttendee'应用于哪个'Workshop'。那有意义吗? – tatlar

+0

我在我的'WorkshopAttendeeFormView'中创建了一个'get()'方法吗?这似乎是这样做的地方... – tatlar

回答

0

原来我太过复杂了。

所有我需要做的是修改form_valid方法Django的GCBV FormView这样:

车间/ views.py

from django.views.generic.edit import FormView 
from workshop.models import Workshop, WorkshopAttendee 
from workshop.forms import WorkshopAttendeeForm 
from django.http import HttpResponseRedirect 

class WorkshopAttendeeFormView(FormView): 

    def form_valid(self, form): 

     self.object = form.save(commit=False) 
     self.object.workshop = Workshop.objects.filter(slug=self.kwargs['slug'])[0] 
     self.object.save() 
     return HttpResponseRedirect(self.get_success_url()) 

这基本上不保存提交表单,但取而代之的是它首先更新它将要保存的对象(WorkshopAttendee对象)和相关的Workshop(基于Workshop slug字段,这是唯一的),然后保存更新后的对象(self.object.save)并将我踢到成功的url。

非常感谢@ init3对他有帮助的指针。非常感激。

+0

啊,这是一个很好的解决方案。干得好的塔特拉 – Thomas

2

你不需要通过PK - 你已经在你的URL中获得它作为slu。。

所以我们可以说这是你的网址:http://example.com/workshops/awesome-workshop-slug/sign_in/urls.py应该是这样的:

url(r'^workshop/(?P<workshop_slug>\w+)/sign_in/$', 
     # ../workshops/awesome-workshop-slug/sign_in/ 
     view = 'workshop_signin', 
     name = 'workshop-signin', 
    ), 

好吧,在你views.py你能做到这一点:

@login_required 
def workshop_signin(request, workshop_slug, template='workshop/sign_in.html'): 
    """Register user to workshop.""" 
    form = WorkshopForm() 
    workshop = Workshop.objects.filter(slug=workshop_slug)[0] 

    if request.method == 'POST': 
     form = WorkshopForm(request.POST, instance=workshop) 
     if form.is_valid(): 
      messages.info(request, 'Yay!') 


    kwargs = { 
     'workshop_form': form, 
    } 
    return render_to_response(template, kwargs, context_instance=RequestContext(request)) 

*未经测试快速和肮脏的代码

+0

感谢@ init3,这让我朝着正确的方向前进。不幸的是,我不能像原样使用你的代码 - 我一直在使用Django的Generic CBV,虽然这让我在右边的[Django源文件](https://github.com/django/django/blob/master /django/views/generic/edit.py) – tatlar

+0

比没有好 - 很高兴我可以帮助一点点:) – Thomas

+1

你让我在解决问题的过程中朝着正确的方向前进,因此提升了你的表现。干杯。 – tatlar