Permalink
Browse files

Rewrite django-announcements

  • Loading branch information...
1 parent 75eca7b commit a5a92003f6f060524ff0215a2b945dde73f97d90 @paltman paltman committed Nov 11, 2011
@@ -1,9 +1 @@
-VERSION = (0, 1, 0, "final")
-
-def get_version():
- if VERSION[3] != "final":
- return "%s.%s.%s%s" % (VERSION[0], VERSION[1], VERSION[2], VERSION[3])
- else:
- return "%s.%s.%s" % (VERSION[0], VERSION[1], VERSION[2])
-
-__version__ = get_version()
+__version__ = "0.2.0.dev1"
@@ -1,20 +1,14 @@
from django.contrib import admin
-from announcements.models import Announcement
-from announcements.forms import AnnouncementAdminForm
+from announcements.models import Announcement, Dismissal
class AnnouncementAdmin(admin.ModelAdmin):
list_display = ("title", "creator", "creation_date", "members_only")
list_filter = ("members_only",)
- form = AnnouncementAdminForm
fieldsets = [
(None, {
- "fields": ["title", "content", "site_wide", "members_only"],
- }),
-
- ("Manage announcement", {
- "fields": ["send_now"],
+ "fields": ["title", "content", "site_wide", "members_only", "publish_start", "publish_end", "dismissal_type"],
}),
]
@@ -26,3 +20,4 @@ def save_model(self, request, obj, form, change):
admin.site.register(Announcement, AnnouncementAdmin)
+admin.site.register(Dismissal)
@@ -1,9 +0,0 @@
-from announcements.models import current_announcements_for_request
-
-
-def site_wide_announcements(request):
- """
- Adds the site-wide announcements to the global context of templates.
- """
- ctx = {"site_wide_announcements": current_announcements_for_request(request, site_wide=True)}
- return ctx
@@ -1,3 +1,7 @@
+import datetime
+
+from django.db.models import Q
+
from atomformat import Feed
from announcements.models import Announcement
@@ -16,7 +20,15 @@ class AnnouncementsBase(Feed):
# def item_links
def items(self):
- return Announcement.objects.order_by("-creation_date")[:10]
+ return Announcement.objects.filter(
+ publish_start__lte=datetime.datetime.now()
+ ).filter(
+ Q(publish_end__isnull=True)|Q(publish_end__gt=datetime.datetime.now())
+ ).filter(
+ site_wide=True
+ ).exclude(
+ members_only=True
+ ).order_by("-creation_date")[:10]
def item_title(self, item):
return item.title
@@ -1,40 +0,0 @@
-from django import forms
-from django.contrib.auth.models import User
-from django.utils.translation import ugettext_lazy as _
-
-try:
- from notification import models as notification
-except ImportError:
- notification = None
-
-from announcements.models import Announcement
-
-
-class AnnouncementAdminForm(forms.ModelForm):
- """
- A custom form for the admin of the Announcement model. Has an extra field
- called send_now that when checked will send out the announcement allowing
- the user to decide when that happens.
- """
-
- send_now = forms.BooleanField(required=False,
- help_text=_("Tick this box to send out this announcement now."))
-
- class Meta:
- model = Announcement
- exclude = ("creator", "creation_date")
-
- def save(self, commit=True):
- """
- Checks the send_now field in the form and when True sends out the
- announcement through notification if present.
- """
-
- announcement = super(AnnouncementAdminForm, self).save(commit)
- if self.cleaned_data["send_now"]:
- if notification:
- users = User.objects.all()
- notification.send(users, "announcement", {
- "announcement": announcement,
- }, on_site=False, queue=True)
- return announcement
@@ -1,16 +0,0 @@
-from django.db.models import get_models, signals
-
-
-try:
- from notification import models as notification
-
- def create_notice_types(app, created_models, verbosity, **kwargs):
- """
- Create the announcement notice type for sending notifications when
- announcements occur.
- """
- notification.create_notice_type("announcement", "Announcement", "you have received an announcement")
-
- signals.post_syncdb.connect(create_notice_types, sender=notification)
-except ImportError:
- print "Skipping creation of NoticeTypes as notification app not found"
@@ -1,63 +1,41 @@
-from datetime import datetime
+import datetime
from django.db import models
-from django.conf import settings
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _
-try:
- set
-except NameError:
- from sets import Set as set # Python 2.3 fallback
-
-
-class AnnouncementManager(models.Manager):
- """
- A basic manager for dealing with announcements.
- """
- def current(self, exclude=[], site_wide=False, for_members=False):
- """
- Fetches and returns a queryset with the current announcements. This
- method takes the following parameters:
-
- ``exclude``
- A list of IDs that should be excluded from the queryset.
-
- ``site_wide``
- A boolean flag to filter to just site wide announcements.
-
- ``for_members``
- A boolean flag to allow member only announcements to be returned
- in addition to any others.
- """
- queryset = self.all()
- if site_wide:
- queryset = queryset.filter(site_wide=True)
- if exclude:
- queryset = queryset.exclude(pk__in=exclude)
- if not for_members:
- queryset = queryset.filter(members_only=False)
- queryset = queryset.order_by("-creation_date")
- return queryset
-
class Announcement(models.Model):
"""
A single announcement.
"""
+ DISMISSAL_NO = 1
+ DISMISSAL_SESSION = 2
+ DISMISSAL_PERMANENT = 3
+
+ DISMISSAL_CHOICES = [
+ (DISMISSAL_NO, "No Dismissals Allowed"),
+ (DISMISSAL_SESSION, "Session Only Dismissal"),
+ (DISMISSAL_PERMANENT, "Permanent Dismissal Allowed")
+ ]
+
title = models.CharField(_("title"), max_length=50)
content = models.TextField(_("content"))
creator = models.ForeignKey(User, verbose_name=_("creator"))
- creation_date = models.DateTimeField(_("creation_date"), default=datetime.now)
+ creation_date = models.DateTimeField(_("creation_date"), default=datetime.datetime.now)
site_wide = models.BooleanField(_("site wide"), default=False)
members_only = models.BooleanField(_("members only"), default=False)
-
- objects = AnnouncementManager()
+ dismissal_type = models.IntegerField(choices=DISMISSAL_CHOICES, default=DISMISSAL_SESSION)
+ publish_start = models.DateTimeField(_("publish_start"), default=datetime.datetime.now)
+ publish_end = models.DateTimeField(_("publish_end"), blank=True, null=True)
def get_absolute_url(self):
- return ("announcement_detail", [str(self.pk)])
- get_absolute_url = models.permalink(get_absolute_url)
+ return reverse("announcement_detail", args=[self.pk])
+
+ def dismiss_url(self):
+ if self.dismissal_type != Announcement.DISMISSAL_NO:
+ return reverse("announcement_dismiss", args=[self.pk])
def __unicode__(self):
return self.title
@@ -67,20 +45,9 @@ class Meta:
verbose_name_plural = _("announcements")
-def current_announcements_for_request(request, **kwargs):
- """
- A helper function to get the current announcements based on some data from
- the HttpRequest.
+class Dismissal(models.Model):
- If request.user is authenticated then allow the member only announcements
- to be returned.
-
- Exclude announcements that have already been viewed by the user based on
- the ``excluded_announcements`` session variable.
- """
- defaults = {}
- if request.user.is_authenticated():
- defaults["for_members"] = True
- defaults["exclude"] = request.session.get("excluded_announcements", set())
- defaults.update(kwargs)
- return Announcement.objects.current(**defaults)
+ user = models.ForeignKey(User, related_name="announcement_dismissals")
+ announcement = models.ForeignKey(Announcement, related_name="dismissals")
+ dismissed_at = models.DateTimeField(default=datetime.datetime.now)
+
@@ -1,3 +0,0 @@
-{{ announcement.title }}
-
-{{ announcement.content }}
@@ -1,36 +0,0 @@
-from django.template import Library, Node
-
-from announcements.models import current_announcements_for_request
-
-
-register = Library()
-
-
-class FetchAnnouncementsNode(Node):
- def __init__(self, context_var, limit=None):
- self.context_var = context_var
- self.limit = limit
-
- def render(self, context):
- try:
- request = context["request"]
- except KeyError:
- raise Exception("{% fetch_announcements %} requires the HttpRequest in context.")
- kwargs = {}
- announcements = current_announcements_for_request(request, **kwargs)
- if self.limit:
- announcements = announcements[:self.limit]
- context[self.context_var] = announcements
- return ""
-
-@register.tag
-def fetch_announcements(parser, token):
- bits = token.split_contents()
- # @@@ very naive parsing
- if len(bits) == 5:
- limit = bits[2]
- context_var = bits[4]
- elif len(bits) == 3:
- limit = None
- context_var = bits[2]
- return FetchAnnouncementsNode(context_var, limit)
@@ -0,0 +1,52 @@
+import datetime
+
+from django import template
+from django.db.models import Q
+
+from announcements.models import Announcement
+
+
+register = template.Library()
+
+
+class AnnouncementsNode(template.Node):
+
+ @classmethod
+ def handle_token(cls, parser, token):
+ bits = token.split_contents()
+ if len(bits) != 3:
+ raise template.TemplateSyntaxError
+ return cls(as_var = bits[2])
+
+ def __init__(self, as_var):
+ self.as_var = as_var
+
+ def render(self, context):
+ request = context["request"]
+ qs = Announcement.objects.filter(
+ publish_start__lte=datetime.datetime.now()
+ ).filter(
+ Q(publish_end__isnull=True)|Q(publish_end__gt=datetime.datetime.now())
+ ).filter(
+ site_wide=True
+ )
+
+ exclusions = request.session.get("excluded_announcements", set())
+ if request.user.is_authenticated():
+ for dismissal in request.user.announcement_dismissals.all():
+ exclusions.add(dismissal.announcement.pk)
+ else:
+ qs = qs.exclude(members_only=True)
+ context[self.as_var] = qs.exclude(pk__in=exclusions)
+ return ""
+
+
+@register.tag
+def announcements(parser, token):
+ """
+ Usage::
+ {% announcements as var %}
+
+ Returns a list of announcements
+ """
+ return AnnouncementsNode.handle_token(parser, token)
@@ -1,35 +0,0 @@
-__test__ = {"ANNOUNCEMENT_TESTS": r"""
->>> from django.contrib.auth.models import User
->>> from announcements.models import Announcement
-
-# create ourselves a user to associate to the announcements
->>> superuser = User.objects.create_user("brosner", "brosner@gmail.com")
-
->>> a1 = Announcement.objects.create(title="Down for Maintenance", creator=superuser)
->>> a2 = Announcement.objects.create(title="Down for Maintenance Again", creator=superuser)
->>> a3 = Announcement.objects.create(title="Down for Maintenance Again And Again", creator=superuser, site_wide=True)
->>> a4 = Announcement.objects.create(title="Members Need to Fill Out New Profile Info", creator=superuser, members_only=True)
->>> a5 = Announcement.objects.create(title="Expected Down Time", creator=superuser, members_only=True, site_wide=True)
-
-# get the announcements that are publically viewable. this is the same as
-# calling as using site_wide=False, for_members=False
->>> Announcement.objects.current()
-[<Announcement: Down for Maintenance Again And Again>, <Announcement: Down for Maintenance Again>, <Announcement: Down for Maintenance>]
-
-# get just the publically viewable site wide announcements
->>> Announcement.objects.current(site_wide=True)
-[<Announcement: Down for Maintenance Again And Again>]
-
-# get the announcements that authenticated users can see.
->>> Announcement.objects.current(for_members=True)
-[<Announcement: Expected Down Time>, <Announcement: Members Need to Fill Out New Profile Info>, <Announcement: Down for Maintenance Again And Again>, <Announcement: Down for Maintenance Again>, <Announcement: Down for Maintenance>]
-
-# get just site wide announcements that authenticated users can see.
->>> Announcement.objects.current(site_wide=True, for_members=True)
-[<Announcement: Expected Down Time>, <Announcement: Down for Maintenance Again And Again>]
-
-# exclude a couple of announcements from the publically viewabled messages.
->>> Announcement.objects.current(exclude=[a1.pk, a5.pk])
-[<Announcement: Down for Maintenance Again And Again>, <Announcement: Down for Maintenance Again>]
-
-"""}
View
@@ -1,18 +1,7 @@
from django.conf.urls.defaults import *
-from django.views.generic import list_detail
-from announcements.models import Announcement
-from announcements.views import *
-
-
-announcement_detail_info = {
- "queryset": Announcement.objects.all(),
-}
urlpatterns = patterns("",
- url(r"^(?P<object_id>\d+)/$", list_detail.object_detail,
- announcement_detail_info, name="announcement_detail"),
- url(r"^(?P<object_id>\d+)/hide/$", announcement_hide,
- name="announcement_hide"),
- url(r"^$", announcement_list, name="announcement_home"),
+ url(r"^(?P<pk>\d+)/$", "announcements.views.detail", name="announcements_detail"),
+ url(r"^(?P<pk>\d+)/hide/$", "announcements.views.dismiss", name="announcement_dismiss")
)
Oops, something went wrong.

0 comments on commit a5a9200

Please sign in to comment.