I've writing an app for managing subscriptions, for example annual club membership. There are different catergories of membership and these categories can have admin specified criteria which could relate to any table in the database. The only requirement is there must be a link back to the Django User table.
I've therefore got this model (defined below) where:
django_content_type
table to identify
the table the criteria are being set for this categorycontent_type
table were User, then this could be
as simple as {"is_active":"true"}
content_type
which is a foreign key for the User tableI want to check the user_link
does link to the User table when the admin saves and I'm writing def clean (self)
for that purpose.
I cannot work out how to convert my content_type
and user_link
fields into an object I can use to check it is the User table. Help very welcome!
Here's models.py
from django.db import models
from django.contrib.auth.models import User
from django.conf import settings
import datetime
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _
from django.contrib.contenttypes.models import ContentType
from subscriptions.fields import JSONField
class Category(models.Model):
name = models.CharField('Category', max_length=30)
content_type = models.ForeignKey(ContentType)
filter_condition = JSONField(default="{}", help_text=_(u"Django ORM compatible lookup kwargs which are used to get the list of objects."))
user_link = models.CharField(_(u"Link to User table"), max_length=64, help_text=_(u"Name of the model field which links to the User table. 'No-link' means this is the User table."), default="No-link")
def clean (self):
if self.user_link == "No-link":
if self.content_type.app_label == "auth" and self.content_type.model == "user":
pass
else:
raise ValidationError(
_("Must specify the field that links to the user table.")
)
else:
t = getattr(self.content_type, self.user_link)
ct = ContentType.objects.get_for_model(t)
if not ct.model == "user":
raise ValidationError(
_("Must specify the field that links to the user table.")
)
def __unicode__(self):
return self.name
def _get_filter(self):
# simplejson likes to put unicode objects as dictionary keys
# but keyword arguments must be str type
fc = {}
for k,v in self.filter_condition.iteritems():
fc.update({str(k): v})
return fc
def object_list(self):
return self.content_type.model_class()._default_manager.filter(**self._get_filter())
def object_count(self):
return self.object_list().count()
class Meta:
verbose_name = _("Category")
verbose_name_plural = _("Categories")
ordering = ('name',)
Different discriptions can have different criteria.
For validation purposes I've got the solution below, which replaces the main else
clause in def clean
.
else:
s = apps.get_model(self.content_type.app_label, self.content_type.model)
if not hasattr(s, self.user_link):
raise ValidationError(
_("Must specify the field that links to the user table.")
)
I now need to work out how to actually use the information and connect the two into a field so I can link through to the User
table