Daniel Quinn
Daniel Quinn

Reputation: 6408

Making a smart class factory in Django

I've been trying to figure this out for a while now with little success. I'm attempting to write a class factory that plays nice with Django's ORM, so that I can take a model schema like this:

Product
    SubclassOfProduct0
    SubclassOfProduct1
    ....

To work like this:

Product.objects.get(pk=7) // returns the result of SubclassOfProduct0(pk=7)
Product.objects.filter(propname="w00t") // returns a QuerySet of Product objects

So I was thinking something like this:

class ProductManager(models.Manager):
    def get(self, *a, **kwa):
        # Get the id from Products (somehow)
        if product.type == Product.TYPE_SUBCLASS0:
            return ProductSubClass0.objects.get(pk=kwa["pk"])


class Product(models.Model):

    TYPE_SUBCLASS0 = 0
    TYPE_SUBCLASS1 = 1

    objects = ProductManager()

    def __init__(self, *a, **kwa):
        self.set_defaults()

    def set_defaults(self):
        pass


class ProductSubClass0(models.Model):
    def set_defaults(self):
        self.type == self.TYPE_SUBCLASS0

...but I don't know how to do it "right". Can someone shed some light here?

Upvotes: 1

Views: 3245

Answers (3)

rcc-e
rcc-e

Reputation: 321

You could use entity framework with generic relations. For example, in models.py:

from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic

# Product
class Product(models.Model):
    name = models.CharField(max_length=128)
    pub_date = models.DateTimeField('date published', null=True)
    productDescription = models.CharField(max_length=400)

    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')


#Shirt Product type
class ShirtProduct(models.Model):
    product  = generic.GenericRelation(Product)



#Book Product type
class BookProduct(models.Model):
    product  = generic.GenericRelation(Product)

....

For search one product id, you can use this method in your ProductManager: product = generic.GenericRelation(Product, content_type_field='content_type_fk', object_id_field='object_primary_key')

(reverse generic relations in the same section of djangoproject page)

Upvotes: 0

Duna C.
Duna C.

Reputation: 329

You could just subclass your Product, as documented here: http://docs.djangoproject.com/en/1.2/topics/db/models/#model-inheritance

class OtherProduct(Product):
    battery_life = …

Maybe also make Product an abstract base class if you don’t need to use it directly.

Upvotes: 0

jbcurtin
jbcurtin

Reputation: 1803

Django Tagging has a great example in the models.py as to how it figures out the content type of specific classes. I'm currently using the pattern in another module I developed with permissions.

Upvotes: 2

Related Questions