diff --git a/announcements/forms.py b/announcements/forms.py new file mode 100644 index 0000000..75a2776 --- /dev/null +++ b/announcements/forms.py @@ -0,0 +1,18 @@ +from django import forms + +from announcements.models import Announcement + + +class AnnouncementForm(forms.ModelForm): + + class Meta: + model = Announcement + fields = [ + "title", + "content", + "site_wide", + "members_only", + "dismissal_type", + "publish_start", + "publish_end" + ] \ No newline at end of file diff --git a/announcements/mixins.py b/announcements/mixins.py new file mode 100644 index 0000000..3749ee5 --- /dev/null +++ b/announcements/mixins.py @@ -0,0 +1,30 @@ +from django.conf import settings +from django.utils.importlib import import_module + + +def _resolve(mixin_setting): + if isinstance(mixin_setting, basestring): + try: + mod_name, klass_name = mixin_setting.rsplit(".", 1) + except ValueError: + raise Exception("Improperly configured.") + try: + mod = import_module(mod_name) + except ImportError: + raise Exception("Could not import %s" % mod_name) + try: + klass = getattr(mod, klass_name) + except AttributeError: + raise Exception("The module '%s' does not contain '%s'." % (mod_name, klass_name)) + mixin_setting = klass + return mixin_setting + + +class DefaultProtectedMixin(object): + + pass + + +ProtectedMixin = _resolve( + getattr(settings, "ANNOUNCEMENTS_PROTECTED_MIXIN", DefaultProtectedMixin) +) diff --git a/announcements/signals.py b/announcements/signals.py new file mode 100644 index 0000000..c1d6d41 --- /dev/null +++ b/announcements/signals.py @@ -0,0 +1,6 @@ +import django.dispatch + + +announcement_created = django.dispatch.Signal(providing_args=["announcement", "request"]) +announcement_updated = django.dispatch.Signal(providing_args=["announcement", "request"]) +announcement_deleted = django.dispatch.Signal(providing_args=["announcement", "request"]) diff --git a/announcements/urls.py b/announcements/urls.py index f0cee50..2798306 100644 --- a/announcements/urls.py +++ b/announcements/urls.py @@ -1,7 +1,15 @@ from django.conf.urls.defaults import * +from announcements.views import detail, dismiss +from announcements.views import CreateAnnouncementView, UpdateAnnouncementView +from announcements.views import DeleteAnnouncementView, AnnouncementListView urlpatterns = patterns("", - url(r"^(?P\d+)/$", "announcements.views.detail", name="announcements_detail"), - url(r"^(?P\d+)/hide/$", "announcements.views.dismiss", name="announcement_dismiss") + url(r"announcement/(?P\d+)/$", detail, name="announcements_detail"), + url(r"announcement/(?P\d+)/hide/$", dismiss, name="announcement_dismiss"), + + url(r"announcement/create/$", CreateAnnouncementView.as_view(), name="announcements_create"), + url(r"announcement/(?P\d+)/update/$", UpdateAnnouncementView.as_view(), name="announcements_update"), + url(r"announcement/(?P\d+)/delete/$", DeleteAnnouncementView.as_view(), name="announcements_delete"), + url(r"", AnnouncementListView.as_view(), name="announcements_list"), ) diff --git a/announcements/views.py b/announcements/views.py index cc1fb0d..1a5b2c8 100644 --- a/announcements/views.py +++ b/announcements/views.py @@ -1,8 +1,14 @@ +from django.core.urlresolvers import reverse from django.http import HttpResponse, HttpResponseNotAllowed from django.shortcuts import get_object_or_404 from django.template.response import TemplateResponse +from django.views.generic.edit import CreateView, UpdateView, DeleteView +from django.views.generic.list import ListView +from announcements.forms import AnnouncementForm +from announcements.mixins import ProtectedMixin from announcements.models import Announcement +from announcements.signals import announcement_created, announcement_updated, announcement_deleted def dismiss(request, pk): @@ -30,3 +36,66 @@ def detail(request, pk): return TemplateResponse(request, "announcements/detail.html", { "announcement": announcement }) + + +class CreateAnnouncementView(CreateView, ProtectedMixin): + + model = Announcement + form_class = AnnouncementForm + + def form_valid(self, form): + self.object = form.save(commit=False) + self.object.creator = self.request.user + self.object.save() + + announcement_created.send( + sender=self.object, + announcement=self.object, + request=self.request + ) + return super(CreateAnnouncementView, self).form_valid(form) + + def get_success_url(self): + return reverse("announcements_list") + + +class UpdateAnnouncementView(UpdateView, ProtectedMixin): + + model = Announcement + form_class = AnnouncementForm + + def form_valid(self, form): + response = super(UpdateAnnouncementView, self).form_valid(form) + announcement_updated.send( + sender=self.object, + announcement=self.object, + request=self.request + ) + return response + + def get_success_url(self): + return reverse("announcements_list") + + +class DeleteAnnouncementView(DeleteView, ProtectedMixin): + + model = Announcement + + def form_valid(self, form): + response = super(DeleteAnnouncementView, self).form_valid(form) + announcement_deleted.send( + sender=self.object, + announcement=self.object, + request=self.request + ) + return response + + def get_success_url(self): + return reverse("announcements_list") + + +class AnnouncementListView(ListView, ProtectedMixin): + + model = Announcement + queryset = Announcement.objects.all().order_by("-creation_date") + paginate_by = 50