I have a set of related models in a Django 1.5 app: Events
that have EventSessions
, and EventSessionRegistrations
that belong to EventSessions
.
I'm struggling to create a class based generic view for a user-facing registration form, where a user registers to attend an EventSession
. Specifically the problem is around excluding the field for which EventSession
the registration is for from being rendered in the form, whilst still setting that value based on the context and/or URL.
I'll try to explain via a use-case first:
'/events/foo/bar'
, where foo
is the Event
, and bar
is the EventSession
. EventSession
, leading to '/events/foo/bar/register/'
. Form for the EventSessionRegistration
model is displayed, but without selecting the EventSession
in the UI, since that information is already "set" by the URL. To acheive this, I have the following view code (lots of other imports etc excluded):
from django.views.generic.edit import CreateView
class RegistrationCreate(CreateView):
form_class = SessionRegistrationForm
success_url = '/thanks/'
template_name = 'events/registration_create.html'
def get_context_data(self, *args, **kwargs):
"""Set the context of which Event, and which EventSession.
Return 404 if either Event or EventSession is not public."""
context = super(RegistrationCreate, self).get_context_data(**kwargs)
s = get_object_or_404(
EventSession,
event__slug=self.kwargs['event_slug'],
event__is_public=True,
slug=self.kwargs['session_slug'],
is_public=True)
context['session'] = s
context['event'] = s.event
return context
URL pattern for this view (included from a base urls.py
):
url(r'^(?P<event_slug>[\w-]+)/(?P<session_slug>[\w-]+)/register/$',
RegistrationCreate.as_view(), name="event_session_registration"),
In the ModelForm, I've tried to convert the ForeignKey session
on EventSessionRegistration field (pointing to EventSession
) to show a HiddenInput()
-widget:
class SessionRegistrationForm(forms.ModelForm):
class Meta:
model = EventSessionRegistration
widgets = {
'session': HiddenInput()
}
But I still don't know how to set the initial value of that field to the id of the 'session'
value that I set in get_context_data
. I've tried setting self.initial = {'session': s.id}
inside get_context_data
, but I'm guessing that the initial
attribute is already used to construct the form at that point.
Any ideas on the best way to acheive this? What am I missing?
Right, I found this question , which deals with the same issue. I ended up with the following overridden post-function in the view, and manually outputting the session id in the template in a hidden field:
def post(self, request, *args, **kwargs):
self.object = None
evt_session = get_object_or_404(
EventSession, pk=int(self.request.POST['session']))
form_class = self.get_form_class()
form = self.get_form(form_class)
form.instance.session = evt_session
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
Also, I found ccbv.co.uk , which is a great resource for finding out about all the methods and attributes in CBV:s, which gave guidance as to how the override should be structured.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.