2014-01-27 26 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