I’m working with my buddy ADubs, esq. on a project where we make it easier to add federation to various models. We’re properly lazy programmers, so we don’t want to rewrite federation for each model we are creating, we just want to mix it in as a general set of functionality. Â Below the fold, more details, sample code, etc.
We will storing two kinds of profiles – one is a local profile and one is for remote users that we know about. We’ll support certain kinds of info about both, and we’ll need to keep some kinds of information different for each. The goal is to make it easy for other folks to take our code and make their own federated user applications. (We’re lazy and we don’t want to write all the applications we want to use ourselves.)
In Django, you create mixins for models through multiple inheritance. Make sure to make your mixin class abstract like so:
#mixins.py from django.db import models from django.utils.translation import ugettext_lazy as _ from datetime import datetime from django import forms from django.contrib.auth.models import User from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes import generic class RemotedProfile(models.Model): uri = models.CharField(_('uri'), unique=True, max_length=600) url = models.URLField(_('URL'), verify_exists=False) publish_object_url = models.CharField(_('publish object URL'), max_length=600, blank=True) post_notice_url = models.CharField(_('post notice URL'), max_length=600, blank=True) update_profile_url = models.CharField(_('update profile URL'), max_length=600, blank=True) created = models.DateTimeField(_('created'), auto_now_add=True) token = models.CharField(_('token'), max_length=300, blank=True) secret = models.CharField(_('secret'), max_length=300, blank=True) class Meta: abstract = True
That’s your mixin code. It defines a bunch of things that a “RemotedProfile” should have. It’s abstract so it will just apply functionality to its inheritors. 1
In models.py
we are going to mix in that remoted profile functionality. We also have abstracted the info we will support for both remote and local profiles. A local profile will support “ProfileDetails”, while a remote profile will support “RemotedProfile” and “ProfileDetails”.
#models.py from datetime import datetime from django.db import models from django import forms from django.contrib.auth.models import User from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes import generic from django.utils.translation import ugettext_lazy as _ from django.db.models.signals import post_save from omb.mixins import RemotedProfile class ProfileDetails(models.Model): about = models.TextField() location = models.TextField() license = models.TextField() fullname = models.CharField(_('full name'), max_length=100, blank=True) homepage = models.URLField(_('homepage'), verify_exists=False, blank=True) bio = models.TextField(_('bio'), blank=True) location = models.CharField(_('location'), max_length=100, blank=True) avatar = models.CharField(_('avatar'), max_length=300, blank=True) class Meta: abstract = True class Profile(ProfileDetails): user = models.ForeignKey(User, unique=True, editable=False) class RemoteProfile(ProfileDetails,RemotedProfile): username = models.CharField(_('username'), max_length=30) class Meta: verbose_name = _('remote profile') verbose_name_plural = _('remote profiles')
I hadn’t seen any examples of multiple mixins on the net, hope this helps out other folks.
- This sentence demonstrates proper use of “it’s” vs “its”. In life, as in programming, syntax matters. (back)