import json
-from django.conf import settings
from django.core import serializers
from django.core.exceptions import MultipleObjectsReturned
from django.core.exceptions import ObjectDoesNotExist
-from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseNotFound
+from django.http import HttpResponse, HttpResponseBadRequest
+from django.views.generic import View
from django.views.generic import DetailView
from django.views.generic import TemplateView
-from django.views.generic.edit import ProcessFormView
-from django.views.generic.edit import ModelFormMixin
from django.views.generic.list import ListView
+from django.views.generic.edit import CreateView
from karmaworld.apps.courses.forms import CourseForm
from karmaworld.apps.courses.models import Course
USER_PROFILE_FLAGS_FIELD = 'flagged_courses'
-class CourseListView(ListView, ModelFormMixin, ProcessFormView):
- """ Simple ListView for the front page that includes the CourseForm """
+# https://docs.djangoproject.com/en/1.5/topics/class-based-views/mixins/#an-alternative-better-solution
+class CourseListView(View):
+ """
+ Composite view to list all courses and processes new course additions.
+ """
+
+ def get(self, request, *args, **kwargs):
+ return CourseListSubView.as_view()(request, *args, **kwargs)
+
+ def post(self, request, *args, **kwargs):
+ ret = CourseAddFormView.as_view()(request, *args, **kwargs)
+ # Check to see if the form came back with errors.
+ if hasattr(ret, 'context_data') and \
+ ret.context_data.has_key('form') and \
+ not ret.context_data['form'].is_valid():
+ # Invalid form. Render as if by get(), but replace the form.
+ badform = ret.context_data['form']
+ request.method = 'GET' # trick get() into returning something
+ ret = self.get(request, *args, **kwargs)
+ # Replace blank form with invalid form.
+ ret.context_data['course_form'] = badform
+ return ret
+
+
+class CourseListSubView(ListView):
+ """ Lists all courses. Called by CourseListView. """
model = Course
- form_class = CourseForm
- object = None
def get_context_data(self, **kwargs):
""" Add the CourseForm to ListView context """
# get the original context
- context = super(CourseListView, self).get_context_data(**kwargs)
+ context = super(CourseListSubView, self).get_context_data(**kwargs)
# get the total number of notes
context['note_count'] = Note.objects.count()
# get the course form for the form at the bottom of the homepage
- context['course_form'] = kwargs.get('course_form', CourseForm())
- if context['course_form'].errors:
- # if there was an error in the form
- context['jump_to_form'] = True
+ context['course_form'] = CourseAddFormView.form_class()
# Include "Add Course" button in header
context['display_add_course'] = True
- # Include settings constants for honeypot
- for key in ('HONEYPOT_FIELD_NAME', 'HONEYPOT_VALUE'):
- context[key] = getattr(settings, key)
-
return context
- def get_success_url(self):
- """ On success, return url based on urls.py definition. """
- return self.object.get_absolute_url()
-
- def form_invalid(self, form, **kwargs):
- """ override form_invalid to populate object_list on redirect """
- kwargs['is_error'] = True
- kwargs['course_form'] = form
- self.object_list = self.get_queryset()
- kwargs['object_list'] = self.object_list
- # hard code errors for the dynamically named honeypot field.
- # This bit will not be necessary when the form is dynamically
- # generated by Django rather than hard coded in the template.
- kwargs['honeypot_errors'] = [x for x in form.errors['honeypot']] \
- if 'honeypot' in form.errors else []
- return self.render_to_response(self.get_context_data(**kwargs))
+
+class CourseAddFormView(CreateView):
+ """ Processes new course additions. Called by CourseListView. """
+ model = Course
+ form_class = CourseForm
+
+ def get_template_names(self):
+ """ template_name must point back to CourseListView url """
+ # TODO clean this up. "_list" template might come from ListView above.
+ return ['courses/course_list.html',]
class CourseDetailView(DetailView):
url(r'^search/$', NoteSearchView.as_view(), name='note_search'),
+ ## Course Model
# VIEW for displaying a single Course
url(r'^course/' + SLUG.format('') + '/$',
CourseDetailView.as_view(), name='course_detail'),
- ## NOTE MODEL
+ ## Note Model
# Ajax endpoint to thank a note
url(r'^ajax/note/thank/(?P<pk>[\d]+)/$', thank_note, name='thank_note'),
# Ajax endpoint to flag a note
#url(r'^(?P<school_slug>[^/]+)/(?P<course_slug>[^/]+)/(?P<slug>[^/]+)$', \
# NoteView.as_view(), name='note_detail'),
- url(r'^$', CourseListView.as_view(model=Course), name='home'),
+ url(r'^$', CourseListView.as_view(), name='home'),
)