How can I create a Create view for a Generic Class model for a model?

What I'm trying to do is a Django template for functional representations. Any help here is greatly appreciated as the documents show examples for viewing the template and list, but I have found very little for model-based general views. Did I miss an example in the docs?

I have a model that represents a calendar entry. There is a foreign key for another object (and not the user) to which the record belongs. What I want to do is simply create an entry to ensure that the foreign key is entered correctly, and then return the user to the corresponding calendar page.

I don’t know, however, how generic class-based views get their URL arguments, and I don’t understand how to set success_url so that it reuses the identifier that was originally passed to the creation URL. Thanks again for your help.

What I'm asking for is essentially what is equivalent to the equivalent of the following class:

def create_course_entry(request, class_id): '''Creates a general calendar entry.''' if request.method == 'POST': form = CourseEntryForm(request.POST) if form.is_valid(): new_entry = form.save(commit=False) new_entry.course = Class.objects.get(pk=class_id) new_entry.full_clean() new_entry.save() return HttpResponseRedirect('/class/%s/calendar/' % class_id) else: form = CourseEntryForm() return render_to_response('classes/course_entry_create.html', { 'class_id': class_id, 'form': form, }, context_instance=RequestContext(request)) 
+7
source share
2 answers

You can subclass the general view of edit.CreateView , set the class / course in the dispatch() method and save it by overriding the form_valid() method:

 from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404 from django.views.generic.edit import CreateView class CourseEntryCreateView(CreateView): form_class = CourseEntryForm model = CourseEntry def dispatch(self, *args, **kwargs): self.course = get_object_or_404(Class, pk=kwargs['class_id']) return super(CourseEntryCreateView, self).dispatch(*args, **kwargs) def form_valid(self, form): self.object = form.save(commit=False) self.object.course = self.course self.object.save() return HttpResponseRedirect(self.get_success_url()) 

If you do not configure CourseEntryForm ModelForm , you can leave the form_class property.

Unfortunately, it is not possible to call super() in the form_valid() method - due to the way it was written, this means that the object will be saved again.

If you need an instance of the class (course?) In the context of the template, you can add it to the get_context_data() method:

  def get_context_data(self, *args, **kwargs): context_data = super(CourseEntryCreateView, self).get_context_data( *args, **kwargs) context_data.update({'course': self.course}) return context_data 
+22
source

An alternative to Matt Austin's answer would be to override the get_form method:

 from django.shortcuts import get_object_or_404 from django.views.generic import CreateView class CourseEntryCreateView(CreateView): form_class = CourseEntryForm model = CourseEntry def get_form(self, form_class): form = super(CustomCreateView, self).get_form(form_class) course = get_object_or_404(Class, pk=self.kwargs['class_id']) form.instance.course = course return form 

So .course is in the CourseEntry instance in context and in the instance created when the form is saved in POST.

+6
source

All Articles