Mercurial > personas_backend
view PersonasBackend/personas/models.py @ 10:fd3e24f5ba18
Added some meta information to models, made save() method of Revision raise an error if client code attempts to modify a revision.
author | Atul Varma <varmaa@toolness.com> |
---|---|
date | Fri, 15 Feb 2008 04:24:00 -0600 |
parents | d7e7916c7c34 |
children | 2b9ce9a2ba72 |
line wrap: on
line source
from django.db import models class User(models.Model): name = models.CharField( "Name of the user", maxlength=100, help_text="This is the user's Mozilla ID.", ) def __str__(self): return self.name class Category(models.Model): class Meta: verbose_name_plural = "categories" name = models.CharField( "Category name", maxlength=50, unique=True, ) def __str__(self): return self.name class Persona(models.Model): MAX_NAME_LENGTH = 50 name = models.CharField( "Title of the Persona", maxlength=MAX_NAME_LENGTH, blank=False, ) category = models.ForeignKey( Category, verbose_name="Category that the Persona is filed under", related_name="personas", null=False, ) description = models.TextField( "Description of the Persona", help_text = "HTML is allowed.", # TODO: Really allow blank descriptions? blank=True, ) header_img = models.URLField( "Header image for the Persona", help_text=("URL for the image that will be placed behind " "the browser's top chrome. Only needs to be " "provided if no URL for the Persona is supplied."), verify_exists=True, blank=True, ) footer_img = models.URLField( "Footer image for the Persona", help_text=("URL for the image that will be placed behind " "the browser's bottom chrome. Only needs to be " "provided if no URL for the Persona is supplied."), verify_exists=True, blank=True, ) url = models.URLField( "URL for the Persona", help_text=("URL for the Persona. Only needs to be provided " "if no header/footer image for the Persona is " "supplied."), verify_exists=True, blank=True, ) update_interval = models.TimeField( "Update interval for the Persona's URL", help_text=("The time interval between which the Persona's " "URL will be refreshed. This field only needs to " "be provided if the URL for the Persona is " "supplied."), null=True, ) MAX_COLOR_SCHEME_LENGTH = 10 color_scheme = models.CharField( "The Persona's color scheme", help_text=("If 'light', any text displayed over the " "Persona will be dark. If 'dark', any text " "displayed over the Persona will be light."), maxlength=MAX_COLOR_SCHEME_LENGTH, choices=(("light", "Light"), ("dark", "Dark")), blank=False, ) date_updated = models.DateTimeField( "Update date for this revision", auto_now=True, null=False, ) updater = models.ForeignKey( User, verbose_name="User who made this revision", related_name="personas", null=True, ) revision = models.PositiveIntegerField( "Revision number for the Persona", help_text=("This number is incremented whenever the Persona " "is changed."), null=False, ) MAX_STATUS_LENGTH = 10 status = models.CharField( "Current status of the Persona", maxlength=MAX_STATUS_LENGTH, choices=(("published", "Published"), ("deleted", "Deleted")), blank=False, default="published", ) def __str__(self): return self.name VERSIONED_PROPERTIES = [ "name", "category", "description", "header_img", "footer_img", "url", "update_interval", "color_scheme", "status", ] def __makeNewRevision(self): """ Detect if any of our versioned properties have changed, and if so, make a new revision. """ original = Persona.objects.get(id=self.id) assert original.revision == self.revision assert original.date_updated == self.date_updated delta = {} for attr in self.VERSIONED_PROPERTIES: origValue = getattr(original, attr) newValue = getattr(self, attr) if origValue != newValue: delta[attr] = origValue if delta: rev = Revision( revision_of = original, date_updated = original.date_updated, updater = original.updater, revision = original.revision ) for attr in delta: setattr(rev, attr, delta[attr]) rev.save() self.revision += 1 def save(self): """ Saves the object. If a versioned property is changed, a new revision is generated automatically. Example: >>> p = Persona(name='Test Persona', ... description='Thos is a test.', ... category=Category.objects.get(name='General')) >>> p.save() >>> p.revision 0 >>> p.revisions.all() [] >>> p.description = 'This is a test.' >>> p.save() >>> p.revision 1 >>> p.revisions.all() [<Revision: Test Persona - r0>] >>> p.revisions.get(revision=0).description 'Thos is a test.' """ if self.id == None: self.revision = 0 else: self.__makeNewRevision() super(Persona, self).save() class Revision(models.Model): class Meta: unique_together = (("revision_of", "revision"),) # Auto-generated fields revision_of = models.ForeignKey( Persona, verbose_name="The Persona that this record is an old revision of", related_name="revisions", null=False, ) date_updated = models.DateTimeField( null=False, ) updater = models.ForeignKey( User, related_name="revisions", null=True, ) revision = models.PositiveIntegerField( null=False, ) # Versioned fields name = models.CharField( maxlength=Persona.MAX_NAME_LENGTH, null=True, ) category = models.ForeignKey( Category, related_name="revisions", null=True, ) description = models.TextField( null=True, ) header_img = models.URLField( null=True, ) footer_img = models.URLField( null=True, ) url = models.URLField( null=True, ) update_interval = models.TimeField( null=True, ) color_scheme = models.CharField( maxlength=Persona.MAX_COLOR_SCHEME_LENGTH, null=True, ) status = models.CharField( maxlength=Persona.MAX_STATUS_LENGTH, null=True, ) def __str__(self): return "%s - r%s" % (self.revision_of.name, self.revision) def save(self): """ The save method for a Revision can only be called once, because Revision objects are meant to be immutable: >>> p = Persona(name='Test Persona', ... category=Category.objects.get(name='General')) >>> p.save() >>> p.description = 'This is a test.' >>> p.save() >>> r = p.revisions.get(revision=0) >>> r.status = "deleted" >>> r.save() Traceback (most recent call last): ... AssertionError: Revisions are immutable """ if self.id == None: super(Revision, self).save() else: raise AssertionError( "Revisions are immutable" )