Merge branch 'penfield'
authorJoseph Spiros <joseph.spiros@ithinksw.com>
Tue, 29 Jun 2010 17:58:35 +0000 (13:58 -0400)
committerJoseph Spiros <joseph.spiros@ithinksw.com>
Tue, 29 Jun 2010 18:03:03 +0000 (14:03 -0400)
* penfield:
  Fleshed out Newsletter, NewsletterArticle, NewsletterIssue, and NewsletterView.
  Moved Tag, and the Titled abstract model, from penfield into philo proper. Added support for a PHILO_PERSON_MODULE setting, and penfield models now refer to that for author fields (by default, it is set to auth.User, so in effect this changes nothing).
  Switching to new Node/View system.
  Tags implemented in Penfield, added to blog entries.
  The index template gets a queryset of entries now.
  Fixed date ordering.
  Fixed blog entries plural and ordering.
  Started implementation of Newsletter models.
  Separating Blogs from the nodes that render them, creating BlogNodes.
  Finished implementing blogs with the exception of tag support.
  Initial skeleton of penfield application, and partial implementation of Entry and Blog models.

contrib/penfield/__init__.py [new file with mode: 0644]
contrib/penfield/admin.py [new file with mode: 0644]
contrib/penfield/models.py [new file with mode: 0644]
models/base.py

diff --git a/contrib/penfield/__init__.py b/contrib/penfield/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/contrib/penfield/admin.py b/contrib/penfield/admin.py
new file mode 100644 (file)
index 0000000..ba885fd
--- /dev/null
@@ -0,0 +1,45 @@
+from django.contrib import admin
+from philo.admin import EntityAdmin
+from philo.contrib.penfield.models import BlogEntry, Blog, BlogView, Newsletter, NewsletterArticle, NewsletterIssue, NewsletterView
+
+
+class TitledAdmin(EntityAdmin):
+       prepopulated_fields = {'slug': ('title',)}
+       list_display = ('title', 'slug')
+
+
+class BlogAdmin(TitledAdmin):
+       pass
+
+
+class BlogEntryAdmin(TitledAdmin):
+       pass
+
+
+class BlogViewAdmin(EntityAdmin):
+       pass
+
+
+class NewsletterAdmin(TitledAdmin):
+       pass
+
+
+class NewsletterArticleAdmin(TitledAdmin):
+       pass
+
+
+class NewsletterIssueAdmin(TitledAdmin):
+       pass
+
+
+class NewsletterViewAdmin(EntityAdmin):
+       pass
+
+
+admin.site.register(Blog, BlogAdmin)
+admin.site.register(BlogEntry, BlogEntryAdmin)
+admin.site.register(BlogView, BlogViewAdmin)
+admin.site.register(Newsletter, NewsletterAdmin)
+admin.site.register(NewsletterArticle, NewsletterArticleAdmin)
+admin.site.register(NewsletterIssue, NewsletterIssueAdmin)
+admin.site.register(NewsletterView, NewsletterViewAdmin)
\ No newline at end of file
diff --git a/contrib/penfield/models.py b/contrib/penfield/models.py
new file mode 100644 (file)
index 0000000..42aca6c
--- /dev/null
@@ -0,0 +1,178 @@
+from django.db import models
+from django.conf import settings
+from philo.models import Tag, Titled, Entity, MultiView, Template, register_value_model
+from django.conf.urls.defaults import url, patterns
+from django.http import Http404, HttpResponse
+from django.template import RequestContext
+from datetime import datetime
+
+
+class Blog(Entity, Titled):
+       pass
+
+
+class BlogEntry(Entity, Titled):
+       blog = models.ForeignKey(Blog, related_name='entries')
+       author = models.ForeignKey(getattr(settings, 'PHILO_PERSON_MODULE', 'auth.User'), related_name='blogentries')
+       date = models.DateTimeField(default=datetime.now)
+       content = models.TextField()
+       excerpt = models.TextField()
+       tags = models.ManyToManyField(Tag)
+       
+       class Meta:
+               ordering = ['-date']
+               verbose_name_plural = "Blog Entries"
+
+
+register_value_model(BlogEntry)
+
+
+class BlogView(MultiView):
+       PERMALINK_STYLE_CHOICES = (
+               ('D', 'Year, month, and day'),
+               ('M', 'Year and month'),
+               ('Y', 'Year'),
+               ('B', 'Custom base'),
+               ('N', 'No base')
+       )
+       
+       blog = models.ForeignKey(Blog, related_name='blogviews')
+       
+       index_template = models.ForeignKey(Template, related_name='blog_index_related')
+       archive_template = models.ForeignKey(Template, related_name='blog_archive_related')
+       tag_template = models.ForeignKey(Template, related_name='blog_tag_related')
+       entry_template = models.ForeignKey(Template, related_name='blog_entry_related')
+       
+       entry_permalink_style = models.CharField(max_length=1, choices=PERMALINK_STYLE_CHOICES)
+       entry_permalink_base = models.CharField(max_length=255, blank=False, default='entries')
+       tag_permalink_base = models.CharField(max_length=255, blank=False, default='tags')
+       
+       @property
+       def urlpatterns(self):
+               base_patterns = patterns('',
+                       url(r'^$', self.index_view),
+                       url((r'^(?:%s)/?' % self.tag_permalink_base), self.tag_view),
+                       url((r'^(?:%s)/(?P<tag>>[-\w]+)/?' % self.tag_permalink_base), self.tag_view)
+               )
+               if self.entry_permalink_style == 'D':
+                       entry_patterns = patterns('',
+                               url(r'^(?P<year>\d{4})/?$', self.archive_view),
+                               url(r'^(?P<year>\d{4})/(?P<month>\d{2})/?$', self.archive_view),
+                               url(r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d+)/?$', self.archive_view),
+                               url(r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d+)/(?P<slug>[-\w]+)/?', self.entry_view)
+                       )
+               elif self.entry_permalink_style == 'M':
+                       entry_patterns = patterns('',
+                               url(r'^(?P<year>\d{4})/?$', self.archive_view),
+                               url(r'^(?P<year>\d{4})/(?P<month>\d{2})/?$', self.archive_view),
+                               url(r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<slug>>[-\w]+)/?', self.entry_view)
+                       )
+               elif self.entry_permalink_style == 'Y':
+                       entry_patterns = patterns('',
+                               url(r'^(?P<year>\d{4})/?$', self.archive_view),
+                               url(r'^(?P<year>\d{4})/(?P<slug>>[-\w]+)/?', self.entry_view)
+                       )
+               elif self.entry_permalink_style == 'B':
+                       entry_patterns = patterns('',
+                               url((r'^(?:%s)/?' % self.entry_permalink_base), self.archive_view),
+                               url((r'^(?:%s)/(?P<slug>>[-\w]+)/?' % self.entry_permalink_base), self.entry_view)
+                       )
+               else:
+                       entry_patterns = patterns('',
+                               url(r'^(?P<slug>>[-\w]+)/?', self.entry_view)
+                       )
+               return base_patterns + entry_patterns
+       
+       def index_view(self, request):
+               entries = self.blog.entries.order_by('-date')
+               return HttpResponse(self.index_template.django_template.render(RequestContext(request, {'blog': self.blog, 'entries': entries})), mimetype=self.index_template.mimetype)
+       
+       def archive_view(self, request, year=None, month=None, day=None):
+               entries = self.blog.entries.all()
+               if year:
+                       entries = entries.filter(date__year=year)
+               if month:
+                       entries = entries.filter(date__month=month)
+               if day:
+                       entries = entries.filter(date__day=day)
+               return HttpResponse(self.archive_template.django_template.render(RequestContext(request, {'blog': self.blog, 'year': year, 'month': month, 'day': day, 'entries': entries})), mimetype=self.archive_template.mimetype)
+       
+       def tag_view(self, request, tag=None):
+               # return HttpResponse(self.tag_template.django_template.render(RequestContext(request, {'blog': self.blog, 'tag': tag, 'entries': None})), mimetype=self.tag_template.mimetype)
+               raise Http404
+       
+       def entry_view(self, request, slug, year=None, month=None, day=None):
+               entries = self.blog.entries.all()
+               if year:
+                       entries = entries.filter(date__year=year)
+               if month:
+                       entries = entries.filter(date__month=month)
+               if day:
+                       entries = entries.filter(date__day=day)
+               try:
+                       entry = entries.get(slug=slug)
+               except:
+                       raise Http404
+               return HttpResponse(self.entry_template.django_template.render(RequestContext(request, {'blog': self.blog, 'entry': entry})), mimetype=self.entry_template.mimetype)
+
+
+class Newsletter(Entity, Titled):
+       pass
+
+
+class NewsletterArticle(Entity, Titled):
+       newsletter = models.ForeignKey(Newsletter, related_name='articles')
+       authors = models.ManyToManyField(getattr(settings, 'PHILO_PERSON_MODULE', 'auth.User'), related_name='newsletterarticles')
+       date = models.DateTimeField(default=datetime.now)
+       lede = models.TextField(null=True, blank=True)
+       full_text = models.TextField()
+
+
+register_value_model(NewsletterArticle)
+
+
+class NewsletterIssue(Entity, Titled):
+       newsletter = models.ForeignKey(Newsletter, related_name='issues')
+       number = models.PositiveIntegerField()
+       articles = models.ManyToManyField(NewsletterArticle)
+
+
+class NewsletterView(MultiView):
+       newsletter = models.ForeignKey(Newsletter, related_name='newsletterviews')
+       
+       index_template = models.ForeignKey(Template, related_name='newsletter_index_related')
+       article_template = models.ForeignKey(Template, related_name='newsletter_article_related')
+       issue_template = models.ForeignKey(Template, related_name='newsletter_issue_related')
+       
+       @property
+       def urlpatterns(self):
+               base_patterns = patterns('',
+                       url(r'^$', self.index_view),
+                       url(r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d+)/(?P<slug>[-\w]+)/?', self.article_view),
+                       url(r'^issues/(?P<number>\d+)/?', self.issue_view),
+               )
+               return base_patterns
+       
+       def index_view(self, request):
+               return HttpResponse(self.index_template.django_template.render(RequestContext(request, {'newsletter': self.newsletter})), mimetype=self.index_template.mimetype)
+       
+       def article_view(self, request, slug, year=None, month=None, day=None):
+               articles = self.newsletter.articles.all()
+               if year:
+                       articles = articles.filter(date__year=year)
+               if month:
+                       articles = articles.filter(date__month=month)
+               if day:
+                       articles = articles.filter(date__day=day)
+               try:
+                       article = articles.get(slug=slug)
+               except:
+                       raise Http404
+               return HttpResponse(self.article_template.django_template.render(RequestContext(request, {'newsletter': self.newsletter, 'article': article})), mimetype=self.article_template.mimetype)
+       
+       def issue_view(self, request, number):
+               try:
+                       issue = self.newsletter.issues.get(number=number)
+               except:
+                       raise Http404
+               return HttpResponse(self.issue_template.django_template.render(RequestContext(request, {'newsletter': self.newsletter, 'issue': issue})), mimetype=self.issue_template.mimetype)
\ No newline at end of file
index f062e2c..3482a1a 100644 (file)
@@ -7,6 +7,25 @@ from philo.utils import ContentTypeRegistryLimiter
 from UserDict import DictMixin
 
 
+class Tag(models.Model):
+       name = models.CharField(max_length=250)
+       slug = models.SlugField()
+       
+       def __unicode__(self):
+               return self.name
+
+
+class Titled(models.Model):
+       title = models.CharField(max_length=255)
+       slug = models.SlugField()
+       
+       def __unicode__(self):
+               return self.title
+       
+       class Meta:
+               abstract = True
+
+
 class Attribute(models.Model):
        entity_content_type = models.ForeignKey(ContentType, verbose_name='Entity type')
        entity_object_id = models.PositiveIntegerField(verbose_name='Entity ID')