Commits

Anonymous committed 517e02e

Initial checkin

Comments (0)

Files changed (10)

+~$
+pyc$

Empty file added.

flat_forum/admin.py

+from django.contrib import admin
+from flat_forum import models
+
+class PostAdmin(admin.ModelAdmin):
+    list_display = ('subject', 'created', 'posted_by', 'reply_to',)
+    date_hierarchy = 'created'
+
+admin.site.register(models.Post, PostAdmin)
+admin.site.register(models.Profile)

flat_forum/fields.py

+from django.db.models.fields import related
+
+class AutoSingleRelatedObjectDescriptor(related.SingleRelatedObjectDescriptor):
+    def __get__(self, instance, instance_type=None):
+        if instance is None:
+            return self
+        try:
+            return getattr(instance, self.cache_name)
+        except AttributeError:
+            params = {'%s__pk' % self.related.field.name: instance._get_pk_val()}
+            db = router.db_for_read(self.related.model, instance=instance)
+            rel_obj = self.related.model._base_manager.using(db).get_or_create(**params)[0]
+            setattr(instance, self.cache_name, rel_obj)
+            return rel_obj
+
+
+class ProfileField(related.OneToOneField):
+    '''A OneToOne field that will create an instance if the target looks us up.'''
+    def contribute_to_related_class(self, cls, related):
+        setattr(cls, related.get_accessor_name(),
+            AutoSingleRelatedObjectDescriptor(related)
+        )

flat_forum/forms.py

+from django import forms
+from flat_forum import models
+
+class PostForm(forms.ModelForm):
+    class Meta:
+        model = models.Post
+        exclude = ['reply_to', 'posted_by', 'created',]
+

flat_forum/models.py

+from django.db import models
+from datetime import datetime
+
+from flat_forum.fields import ProfileField
+
+class Profile(models.Model):
+    user = ProfileField('auth.User', related_name='forum_profile')
+
+    def __unicode__(self):
+        return self.user.get_full_name() or self.user.username
+
+from django.contrib.auth.models import User
+User.forum_profile = property(lambda u: Profile.objects.get_or_create(user=u)[0])
+
+class Post(models.Model):
+    reply_to = models.ForeignKey('self', blank=True, null=True, related_name='replies')
+    posted_by = models.ForeignKey('Profile', related_name='posts')
+    created = models.DateTimeField(default=datetime.now)
+    subject = models.CharField(max_length=200)
+    content = models.TextField(blank=True)
+
+    class Meta:
+        get_latest_by = 'created'
+        ordering = ('created',)
+        permissions = (
+            ('can_reply', 'Can reply to Posts'),
+        )
+    def __unicode__(self):
+        return 'Post on %s by %s' % (self.created, self.posted_by,)
+
+    @models.permalink
+    def get_absolute_url(self):
+        return 'post-detail', (), {'pk': self.pk}

flat_forum/search_indexes.py

+import datetime
+from haystack.indexes import *
+from haystack import site
+from flat_forum.models import Post
+
+class PostIndex(SearchIndex):
+    text = CharField(document=True, use_template=True)
+    author = CharField(model_attr='posted_by')
+    pub_date = DateTimeField(model_attr='created')
+
+    def index_queryset(self):
+        return Post.objects.all()
+
+site.register(Post, PostIndex)

flat_forum/urls.py

+from django.conf.urls.defaults import patterns, url
+
+urlpatterns = patterns('flat_forum.views',
+    url(r'^new/$', 'post_add', name='post-add'),
+    url(r'^(?P<pk>\d+)/$', 'post_detail', name='post-detail'),
+    url(r'^(?P<pk>\d+)/reply/$', 'post_reply', name='post-reply'),
+    # Default view use a Haystack Search view
+    url(r'^$', 'post_index',),
+)
+

flat_forum/views.py

+from flat_forum import models, forms
+from django.views import generic
+from django.views.generic import edit
+from django.db.models import Q
+from django.shortcuts import get_object_or_404
+from django.contrib.auth.decorators import permission_required
+
+import shlex
+
+class PostListView(generic.ListView):
+    model = models.Post
+
+    def get_queryset(self):
+        qset = super(PostListView, self).get_queryset()
+        terms = self.request.GET.get('q', '').encode('utf8')
+        for term in shlex.split(terms):
+            qset = qset.filter(
+                Q(subject__icontains=term) | Q(content__icontains=term)
+            )
+        return qset
+
+post_index = PostListView.as_view()
+
+class PostCreateView(generic.CreateView):
+    '''Create a brand new post'''
+    model = models.Post
+    form_class = forms.PostForm
+
+    def form_valid(self, form):
+        obj = form.save(commit=False)
+        if 'pk' in self.kwargs:
+            obj.reply_to = get_object_or_404(models.Post, pk=self.kwargs['pk'])
+        obj.posted_by = self.request.user.forum_profile
+        self.object = obj.save()
+        return super(PostCreateView, self).form_valid(form)
+
+post_add = permission_required('post.can_add')(PostCreateView.as_view())
+post_reply = permission_required('post.can_reply')(PostCreateView.as_view())
+
+class PostDetail(generic.DetailView, edit.BaseCreateView):
+    model = models.Post
+    form_class = forms.PostForm
+
+    def form_valid(self, form):
+        obj = form.save(commit=False)
+        obj.reply_to = get_object_or_404(models.Post, pk=self.kwargs['pk'])
+        obj.posted_by = self.request.user.forum_profile
+        self.object = obj.save()
+        return super(PostDetail, self).form_valid(form)
+
+    def get_context_data(self, **kwargs):
+        return dict(super(PostDetail, self).get_context_data(**kwargs),
+            form=forms.PostForm(),
+        )
+
+post_detail = PostDetail.as_view()
+
+from setuptools import setup, find_packages
+
+setup( name='flat_forum',
+    version = '0.1',
+    description = 'A new approach to online Forums',
+    author = 'Curtis Maloney',
+    author_email = 'curtis@tinbrain.net',
+    url = 'http://bitbucket.org/funkybob/flat_forum/',
+    keywords = ['django', 'forum',],
+    packages = find_packages(),
+    include_package_data = True,
+    zip_safe = False,
+    classifiers = [
+        'Environment :: Web Environment',
+        'Framework :: Django',
+        'License :: OSI Approved :: BSD License',
+        'Operating System :: OS Independent',
+        'Programming Language :: Python',
+    ],
+    install_requires = [
+        'Django>=1.3',
+        'django-taggit',
+    ]
+)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.