Skip to content

Instantly share code, notes, and snippets.

@gcavalcante8808
Created June 8, 2013 15:04
Show Gist options
  • Save gcavalcante8808/5735441 to your computer and use it in GitHub Desktop.
Save gcavalcante8808/5735441 to your computer and use it in GitHub Desktop.
IronWiki --> models
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group
from mptt.models import MPTTModel, TreeForeignKey
#TODO: Handle the change agains current revision. At this moment, the change is manual.
class Article(MPTTModel):
"""
This is where informations about last revision and permissions are stored.
"""
name = models.CharField(max_length=255, null=True)
#TODO: there is no title? title is located at the current revision. WTF??
current_revision = models.OneToOneField('ArticleRevision',
verbose_name=_(u'current revision'),
blank=True, null=True, related_name='current_set',
help_text=_(
u"""The revision being displayed for this article.
If you need to do a roll-back, simply change the value of this field."""),
)
created = models.DateTimeField(auto_now_add=True, verbose_name=_(u'created'), )
modified = models.DateTimeField(auto_now=True, verbose_name=_(u'modified'),
help_text=_(u'Article properties last modified'))
owner = models.ForeignKey(get_user_model(), verbose_name=_('owner'),
blank=True, null=True, related_name='owned_articles',
help_text=_(
u"""The owner of the article, usually the creator. The owner always has both read
and write access.""")
)
group = models.ManyToManyField(Group, verbose_name=_('group'),
blank=True, null=True,
help_text=_(
u"""Like in a UNIX file system, permissions can be given to a user according to
group membership. Groups are handled through the Django auth system."""))
available = models.BooleanField(verbose_name=_(u"Is this article available?"),
default=True, help_text=_(
_(u"The availability of the article. Moderators can change this.")
))
parent = TreeForeignKey('self', null=True, blank=True, related_name='children')
def __unicode__(self):
if self.current_revision:
return self.current_revision.title
else:
return self.name
class MPTTMeta:
order_insertion_by = ['name']
permissions = (
("can_moderate", _(u"Can moderate the article")),
("can_assign", _(u"Can assign the article for a user or group")),
)
class BaseRevisionMixin(models.Model):
"""This is an abstract model used as a mixin: Do not override any of the
core model methods but respect the inheritor's freedom to do so itself."""
revision_number = models.IntegerField(editable=False, verbose_name=_(u'revision number'))
user_message = models.TextField(blank=True, )
automatic_log = models.TextField(blank=True, editable=False, )
ip_address = models.IPAddressField(_('IP address'), blank=True, null=True, editable=False)
user = models.ForeignKey(get_user_model(), verbose_name=_('user'),
blank=True, null=True,
on_delete=models.SET_NULL)
modified = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)
previous_revision = models.ForeignKey(
'self', blank=True, null=True, on_delete=models.SET_NULL, editable=False
)
# NOTE! The semantics of these fields are not related to the revision itself
# but the actual related object. If the latest revision says "deleted=True" then
# the related object should be regarded as deleted.
deleted = models.BooleanField(verbose_name=_(u'deleted'), editable=False)
locked = models.BooleanField(verbose_name=_(u'locked'))
def set_from_request(self, request):
if request.user.is_authenticated():
self.user = request.user
# if settings.LOG_IPS_USERS:
# self.ip_address = request.META.get('REMOTE_ADDR', None)
# elif settings.LOG_IPS_ANONYMOUS:
# self.ip_address = request.META.get('REMOTE_ADDR', None)
class Meta:
abstract = True
class ArticleRevision(BaseRevisionMixin, models.Model):
"""This is where main revision data is stored. To make it easier to
copy, do NEVER create m2m relationships."""
article = models.ForeignKey('Article', on_delete=models.CASCADE,
verbose_name=_(u'article'), blank=True, null=True)
# This is where the content goes, with whatever markup language is used
content = models.TextField(blank=True, verbose_name=_(u'article contents'))
# This title is automatically set from either the article's title or
# the last used revision...
title = models.CharField(max_length=512, verbose_name=_(u'article title'),
null=False, blank=False, help_text=_(
u'Each revision contains a title field that must be filled out, even if the title has not changed'))
url = models.SlugField(max_length=512, null=False, blank=False, unique=True,
help_text=_(u"""
Especific URL of the article. Cannot be changed after the first time when saving a revision.
"""))
# TODO:
# Allow a revision to redirect to another *article*. This
# way, we can redirects and still maintain old content.
#redirect = models.ForeignKey('Article', null=True, blank=True,
# verbose_name=_(u'redirect'),
# help_text=_(u'If set, the article will redirect to the contents of another article.'),
# related_name='redirect_set')
def __unicode__(self):
return "%s (%d)" % (self.title, self.revision_number)
def save(self, *args, **kwargs):
if (not self.id and
not self.previous_revision and
self.article and
self.article.current_revision and
self.article.current_revision != self):
self.previous_revision = self.article.current_revision
if not self.revision_number:
try:
previous_revision = self.article.articlerevision_set.latest()
self.revision_number = previous_revision.revision_number + 1
except ArticleRevision.DoesNotExist:
self.revision_number = 1
super(ArticleRevision, self).save(*args, **kwargs)
if not self.article.current_revision:
# If I'm saved from Django admin, then article.current_revision is me!
self.article.current_revision = self
self.article.save()
class Meta:
get_latest_by = ('revision_number',)
ordering = ('created',)
unique_together = ('article', 'revision_number')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment