2010-04-03 215 views
1

我有一個編輯我的模型實例的窗體。我希望使用表單將所有值隱藏起來,並且初始值爲username默認爲登錄用戶,以便它變成subscribe表單。問題是,正常initial={'field':value}似乎不適用於許多領域。我該如何去做呢?Django初始化ManyToMany字段

我views.py

@login_required 
def event_view(request,eventID): 
    user = UserProfile.objects.get(pk=request.session['_auth_user_id']) 
    event = events.objects.get(eventID = eventID) 
    if request.method == 'POST': 
     form = eventsSusbcribeForm(request.POST,instance=event) 
     if form.is_valid(): 
      form.save() 
      return HttpResponseRedirect('/events/') 

    else: 
     form = eventsSusbcribeForm(instance=event) 

    return render_to_response('event_view.html', {'user':user,'event':event, 'form':form},context_instance = RequestContext(request)) 

我forms.py

class eventsSusbcribeForm(forms.ModelForm): 
    eventposter = forms.ModelChoiceField(queryset=UserProfile.objects.all(), widget=forms.HiddenInput()) 
    details = forms.CharField(widget=forms.Textarea(attrs={'cols':'50', 'rows':'5'}),label='Enter Event Description here') 
    date = forms.DateField(widget=SelectDateWidget()) 


    class Meta: 
     model = events 
     exclude = ('deleted') 

    def __init__(self, *args, **kwargs): 
     super(eventsSusbcribeForm, self).__init__(*args, **kwargs) 
     self.fields['username'].initial = (user.id for user in UserProfile.objects.filter()) 

我的models.py

class events(models.Model): 
    eventName = models.CharField(max_length=100) 
    eventID = models.AutoField(primary_key=True) 
    details = models.TextField() 
    attendanceFee = models.FloatField(max_length=99) 
    date = models.DateField() 
    username = models.ManyToManyField(UserProfile, related_name='user', blank=True) 
    eventposter = models.ForeignKey(UserProfile, related_name='event_poster') 
    deleted = models.BooleanField() 

    def __unicode__(self): 
     return u'%s' % (self.eventName) 

回答

8

您可以發佈您的活動模式?如果沒有這個,你很難猜測你想要做什麼。沒有它我必須承擔一些事情,所以如果我錯了,我很抱歉。

首先,我猜你不應該使用EventSubscriptionForm的Event ModelForm。這沒有什麼意義。我們希望,您創建了一個通過類事件和用戶,所以在你的事件模型,您有類似

subscriber_users = models.ManyToManyField(User, through="Subscription") 

class Subscription(models.Model): 
    user = models.ForeignKey(User, related_name="events",) 
    event = models.ForeignKey(Event, related_name="subscribers") 

然後你可以使用訂閱的ModelForm。

是否有任何原因您使用eventID而不是django idiom,event_id?您還應該使用Pythonic套件導入您的Event和EventSubcribeForm類。其中一個重要的是,你應該將所有內容鏈接到User而不是UserProfile。

技術上講,它更有意義的視圖設置的初始而非初始化形式,因爲你將不得不通過request.user到初始化反正。

我想你應該嘗試一下本作你的看法......

@login_required 
def event_view(request, event_id=None): 
    user = request.user.get_profile() 
    event = Event.objects.get(id=event_id) 
    initial = {'user': request.user} 

    form = EventSubcriptionForm(request.POST or None, instance=event, initial=initial) 
    if form.is_valid(): 
     form.save() 
     return HttpResponseRedirect(reverse('event_list')) 

    return render_to_response('event_view.html', { 
     'event': event, 
     'form': form 
    }, context_instance = RequestContext(request)) 

的幾個注意事項

  • 使用request.user.get_profile()爲當前用戶的配置文件對象
  • 你可以使用request.POST or None來避免請求。方法案例
  • 始終使用指定的網址,因此您可以將名稱顛倒而不是將網址硬編碼爲視圖
  • 如果你想在你的模板上下文中使用user,只需設置一個上下文處理器(請參閱pinax,瞭解如何執行此操作),而不是將它傳遞到每個視圖中。你也可以使用request.user。

請記住,如果你有過類設置就像我說的這個代碼將只工作,可使用窗體像

class EventSubcriptionForm(forms.ModelForm): 
    class Meta: 
     model = Subscription 
     exclude = ('event') 

編輯 感謝一大堆的窗口。我對django並不陌生,但是對於SO來說卻是一個非常新的東西。

好的,你應該讀一些關於Python約定http://www.python.org/dev/peps/pep-0008/的PEP或關於它的一些SO帖子What is the naming convention in Python for variable and function names?

這裏就是我爲您推薦活動應用models.py:

class Event(models.Model): 
    name = models.CharField(max_length=100) 
    details = models.TextField() 
    attendance_fee = models.FloatField(max_length=99) 
    date = models.DateField() 
    poster = models.ForeignKey(User, related_name='events_posted') 
    deleted = models.BooleanField() 

    attendee_users = models.ManyToManyField(User, through="Attendance") 

    def __unicode__(self): 
     return self.name 

class Attendance(models.Model): 
    user = models.ForeignKey(User, related_name="events",) 
    event = models.ForeignKey(Event, related_name="attendees") 

  • 一類的名稱是大寫和奇異。你沒有描述事件,你是一個事件的藍圖。
  • 你永遠不需要在其屬性中的類的名稱,即event_name可以只是名稱。
  • 所有變量均爲小寫_和_未編碼
  • 始終爲鏈接到用戶,而不是您的個人檔案模型。很多django代碼都期望這樣做。

所以現在您可以通過event.attendees訪問參加活動的用戶。

+0

我是一個新手,蟒蛇,所以我可能不熟悉的機智,你已經指出標準的約定。將會把它放到我的下一個項目中,因爲我幾乎要完成這個項目。我正在使用UserProfile,因爲我將用戶分類並擴展了其功能。 感謝您提供'reverse'方法的提示。 我必須改變我的事件模型,以便我可以使用'through'。我已經完成了我的ERD和DFD,所以Iam試圖避免對我的模型進行更改。 – 2010-04-04 10:29:19

+0

有關用戶配置文件,請參見http://www.b-list.org/weblog/2006/jun/06/django-tips-extending-user-model/。你不應該子類User。 是的,你必須做模式遷移來使用一個通過,因爲必須已經有一個events_users鏈接表。 請原諒我,如果我錯了,但這些只是圖表正確嗎?如果您仍在開發中,重置數據庫有什麼問題? – 2010-04-04 16:06:40

1

我在嘗試爲manytomany設置默認值時發現了這個問題。我不想添加直通表。

基於Casey發佈的視圖,但在許多關係中添加用戶。

初始職位:

@login_required 
def event_view(request, event_id=None): 
    user = request.user.get_profile() 
    event = Event.objects.get(id=event_id) 
    initial = {'user': request.user, 'username': [ request.user.id, ] } # makes the poster also an attendee 

    form = EventSubcriptionForm(request.POST or None, instance=event, initial=initial) 
    if form.is_valid(): 
     form.save() 
     return HttpResponseRedirect(reverse('event_list')) 

    return render_to_response('event_view.html', { 
     'event': event, 
     'form': form 
    }, context_instance = RequestContext(request)) 

更新版本:

@login_required 
def event_view(request, event_id=None): 
    user = request.user.get_profile() 
    event = Event.objects.get(id=event_id) 
    initial = {'user': request.user, 'subscriber_users': [ request.user.id, ] } # makes the poster also an subscriber 

    form = EventSubcriptionForm(request.POST or None, instance=event, initial=initial) 
    if form.is_valid(): 
     form.save() 
     return HttpResponseRedirect(reverse('event_list')) 

    return render_to_response('event_view.html', { 
     'event': event, 
     'form': form 
    }, context_instance = RequestContext(request))