The document discusses Django's contenttypes framework which allows working with models generically without having to know the specific model being used. It presents several patterns for implementing generic functionality, including self-aware models, improved generic views, universal URLs, and dynamic forms. The key benefits are the ability to perform CRUD operations and create relationships between any objects without having to pre-program for each specific model.
3. CONTENTTYPES An application that can track all of the models installed in your Django-powered project, providing a high-level, generic interface for working with your models
6. PROBLEM blog = Blog.objects.get( pk = 1 ) posts = Post.objects.filter( blog = blog ) features = Post.objects.filter( feature = True ) 3+ URLs 3+ view function 3+ templates
7. PROBLEM blog = Blog.objects.get( pk = 1 ) posts = Post.objects.filter( blog = blog ) features = Post.objects.filter( feature = True ) {%for post in posts %} {{ post.title }} {{ post.like_set.count }} likes {%endfor%}
9. GENERIC VIEWS? Take certain common idioms and patterns found in view development and abstract them so that you can quickly write common views of data without having to write too much code
17. MORE PROBLEMS classFeature(models.Model): title = models.CharField() post = models.ForeignKey( Post ) likers = models.ForeignKey( User ) likes = models.IntegerField()
18. CONTENTTYPES An application that can track all of the models installed in your Django-powered project, providing a high-level, generic interface for working with your models
19. CONTENTTYPES Use the ORM without knowing what kind of objects you might be working with.
20. CONTENTTYPES Use the ORM without knowing what kind of objects you might be working with. EVER.
31. MORE PROBLEMS classLike( models.Model ): content_type = models.ForeignKey( ContentType ) object_id = models.PositiveIntegerField() content_object = generic.GenericForeignKey( ... ) likers = models.ManyToMany( User ) deflike_view( request, object_id ): post = Post.objects.get( pk = object_id ) like = Like( object_id = post, ??? )
32. GENERIC GEMS from django.contrib.contenttypes.models importContentType from django.contrib.auth.models importUser >>> type = ContentType.objects.get_for_model( User ) >>> type >>> <ContentType: user > >>> model = type.model_class() >>> model >>> <class: 'django.contrib.auth.models.User'>
36. SELF AWARE MODEL classSelfAwareModel(models.Model): def get_ct( self ): ''' Returns the Content Type for this instance''' return ContentType.objects.get_for_model(self) def get_ct_id( self ): ''' Returns the id of the content type for this instance''' return self.get_ct().pk def get_app_label( self ): return self.get_ct().app_label def get_model_name( self ): return self.get_ct().model classMeta: abstract = True
37. SELF AWARE MODEL classSelfAwareModel(models.Model): def get_ct( self ): ''' Returns the Content Type for this instance''' return ContentType.objects.get_for_model(self) def get_ct_id( self ): ''' Returns the id of the content type for this instance''' return self.get_ct().pk def get_app_label( self ): return self.get_ct().app_label def get_model_name( self ): return self.get_ct().model classMeta: abstract = True CACHED BY DJANGO
38. SELF AWARE MODEL classSelfAwareModel(models.Model): def get_ct( self ): ''' Returns the Content Type for this instance''' return ContentType.objects.get_for_model(self) def get_ct_id( self ): ''' Returns the id of the content type for this instance''' return self.get_ct().pk def get_app_label( self ): return self.get_ct().app_label def get_model_name( self ): return self.get_ct().model classMeta: abstract = True CACHED BY DJANGO self.__class__._cache[self.db][key]
39. SELF AWARE EVERYTHING classPost( SelfAwareModel ): title = models.CharField() blog = models.ForeignKey( Blog ) body = models.TextField() slug = models.SlugField() likers = models.ForeignKey( User ) likes = models.IntegerField()
40. SELF AWARE EVERYTHING classPost( SelfAwareModel ): title = models.CharField() blog = models.ForeignKey( Blog ) body = models.TextField() slug = models.SlugField() likers = models.ForeignKey( User ) likes = models.IntegerField() ALL MODELS SUBCLASSE SELFAWAREMODEL
41. SELF AWARE EVERYTHING classPost( SelfAwareModel ): title = models.CharField() blog = models.ForeignKey( Blog ) body = models.TextField() slug = models.SlugField() likers = models.ForeignKey( User ) likes = models.IntegerField() @permalink def get_absolute_url( self ): ... >>> post = Post.objects.latest() >>> obj.get_ct() >>> <ContentType: post>
42. SELF AWARE EVERYTHING classPost( SelfAwareModel ): title = models.CharField() blog = models.ForeignKey( Blog ) body = models.TextField() slug = models.SlugField() likers = models.ForeignKey( User ) likes = models.IntegerField() @permalink def get_absolute_url( self ): ... I KNOW MY CONTENT TYPE >>> post = Post.objects.latest() >>> obj.get_ct() >>> <ContentType: post>
62. MAGIC FORMS defedit_object( request, ct_id, obj_id ): obj = utils.get_object( ct_id, obj_id ) form = ??? Can't predefine ModelForm when you don't know what model you're working with