views:

300

answers:

1

I have a form that edits an instance of my model. I would like to use the form to pass all the values as hidden with an inital values of username defaulting to the logged in user so that it becomes a subscribe form. The problem is that the normal initial={'field':value} doesn't seem to work for manytomany fields. how do i go about it?

my 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 ))

my 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())

my 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)
+1  A: 

Can you post your Event model? It's too hard to guess what you are trying to do without that. I have to assume a few things without it, so I'm sorry if I'm wrong.

First off, I'm guessing that you should not be using an Event ModelForm for the EventSubscriptionForm. That doesn't really make sense. Hopefully, you created a through class for Event and User, so in your Event model, you have something like

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

and

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

Then you can use a Subscription ModelForm.

Is there any reason you're using eventID instead of the django idiom, event_id? You should also import your Event and EventSubcribeForm classes with Pythonic casing. One very important thing is that you should be linking everything to User and not UserProfile.

Technically, it makes more sense to set initial in the view rather than the form init, because you would have to pass request.user to init anyway.

I think you should try this for your view...

@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))

A few notes

  • use request.user.get_profile() for the current user's profile object
  • you can use request.POST or None to avoid the request.method cases
  • always use named urls so you can reverse on names instead of hard-coding urls into views
  • if you want user in your template context, just setup a context processor (see pinax for example on how to do this) instead of passing it in every single view. You can always use request.user also.

Keep in mind that this code will only work if you have that through class setup like I said and you use a form like

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

EDIT Thanks a bunch for the ups. I'm not new to django, but somehow very new to SO.

Okay, you should really read some of the PEPs about Python conventions http://www.python.org/dev/peps/pep-0008/ or some SO posts about it http://stackoverflow.com/questions/159720/what-is-the-naming-convention-in-python-for-variable-and-function-names.

Here's what I recommend for your event app 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")

Notes

  • The name of a class is capitalized and singular. You are not describing events, you are the blueprint for an Event.
  • you never need the name of the class in its attributes, i.e. event_name can just be name.
  • all variables are lowercase_and_underscored
  • always link to User, not your profile model. A lot of django code expects this.

So now you can access the users attending the event with event.attendees.

Casey Stark
i am a python newbie, so I may not be familiar wit the standard conventions that you have pointed. will put that in my next project since am almost through with this one. I am using UserProfile because I subclassed user and extended its functionality. Thanks for the tip in `reverse` method. do i have to change my event model so that I can use `through`. I had already done my ERDs and DFDs, so Iam trying to avoid doing changes on my models.
See http://www.b-list.org/weblog/2006/jun/06/django-tips-extending-user-model/ for user profiles. You shouldn't subclass User.And yes, you do have to do schema migration to use a through because there must already be a events_users linking table.Forgive me if I'm wrong but those are just diagrams right? What's wrong with reseting your database if you're still in development?
Casey Stark