2010-04-03 118 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))