Did you know? DZone has great portals for Python, Cloud, NoSQL, and HTML5!
Python Zone is brought to you in partnership with:

Rob Golding is a web applications developer from the UK, specializing in Python and Django with 3 years of experience in the trade as a systems administrator. Rob is a DZone MVB and is not an employee of DZone and has posted 5 posts at DZone. You can read more from them at their website. View Full User Profile

Model Templates in Django without Denormalization

02.05.2012
Email
Views: 1372
  • submit to reddit
This content is part of the Python Zone, which is presented to you by DZone and New Relic. Visit the Python Zone for news, tips, and tutorials on the Python programming language.  New Relic provides the resources and best practices to help you monitor these applications.

I came across an interesting problem recently, while trying to model the structure of a university course in Django.

The model needed to represent the notion of a university module, which can be taught over a number of semesters and/or years, by different people, and with different students each time round. Some information remained common to each of these modules however, such as the code, name, and type of the module (single semester or full-year).

One solution that crossed my mind was to use a sort of template, and copy the common information over each time the module was taught. This would mean duplicating the common fields over a template model and the module’s model, and copying the data every time a new “Module” object gets created. This just didn’t sit well with me though, as I really don’t like denormalising data when it’s not absolutely necessary.

The solution I have settled on (for now, anyway) works something like this: I use the model template idea, but with a foreign key from the Module to it’s template. Then, to access the fields on the template directly from the Module model, I use a combination of the Python property and a smart lambda function.

Here’s a simplified version of the model to illustrate what I’m talking about:

models.py

class ModuleDefinition(models.Model):
code = models.CharField(max_length=6, unique=True)
name = models.CharField(max_length=200)
credits = models.IntegerField(max_length=4)
level = models.IntegerField(max_length=2)
type = models.CharField(max_length=30, choices=MODULE_TYPE_CHOICES)
class Module(models.Model):
code = property(lambda s: s._get_definition_property('code'))
name = property(lambda s: s._get_definition_property('name'))
credits = property(lambda s: s._get_definition_property('credits'))
level = property(lambda s: s._get_definition_property('level'))
definition = models.ForeignKey('ModuleDefinition')
semester = models.CharField(max_length=20, choices=SEMESTER_CHOICES)
year = models.CharField(max_length=20, choices=YEAR_CHOICES)
convener = models.ForeignKey('auth.User', related_name='modules_convened')
students = models.ManyToManyField('auth.User', blank=True, related_name='modules_taken')
def _get_definition_property(self, property):
return self.definition.__getattribute__(property) 


In this model I’ve called the template a “definition”, but the idea is the same. The _get_definition_property() method allows me to get a property from the parent definition programmatically, which is used in the lambda functions to add the fields from the definition to the model itself, as read-only properties. This allows me to access them as if they were a field stored on the model itself (i.e. module.code, module.name, etc.) which is handy in the templates where module.definition.code would get very old, very fast.

I’d be really interested to hear how others have tackled the same issue, as I’m sure it’s not just restricted to university modules. Maybe soon I’ll be making a post about how I model a timetable in Django…after all, how hard can it be!?

Oh, and if you’re wondering, this code is for the MyUni project that is occupying me recently. I’m restricting myself to just thinking about how the models could work (and maybe writing little bit of code) until Rob and Ben come back to university.


Source: http://www.robgolding.com/blog/2010/04/27/django-model-templates-sans-denormalisation/

Tags:
Published at DZone with permission of Rob Golding, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Python is a fast, powerful, dynamic, and versatile programming language that is being used in a variety of application domains. It has flourished as a beginner-friendly language that is penetrating more and more industries. The Python Zone is a community that features a diverse collection of news, tutorials, advice, and opinions about Python and Django. The Python Zone is sponsored by New Relic, the all-in-one web application performance tool that lets you see performance from the end user experience, through servers, and down to the line of application code.