Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Django ContentType Usage

Tech 1

1. Introduction


ContentType solves the problem where two fields in one table are associated with two (or more) other tables.

# Course Table - Free Courses
# id         name     
   1         Linux Basics                   
   2         Python Basics                       


# DegreeCourse Table - Degree Courses
# id         name        
   1         Python Full Stack               


# PricePolicy Table - Two fields correspond to the id and table name of the above tables
# id        day        price        course_id        course_type
   1         7          0            1                Free Course
   2         7          0            2                Free Course
   3         14         9.9          2                Free Course
   4         180        18888        1                Degree Course   

Modify the PricePolicy table to associate with Django's content_type, which stores all table names in Django.

# PricePolicy Table
# id         day         price        course_id    course_type(foreign key)
   1         7           0            1            1
   2         14          9.9          1            1
   3         180         18888        1            2  


# ContentType Table
id         model            app_label
1          course            app01
2          degreecourse      app01  

2. Custom Methods for Operations


Model Definitions

from django.db import models

class Course(models.Model):
    name = models.CharField(max_length=32)
    def __str__(self):
        return self.name

class DegreeCourse(models.Model):
    name = models.CharField(max_length=32)
    def __str__(self):
        return self.name

# Using ContentType but not its methods
from django.contrib.contenttypes.models import ContentType
class PricePolicy(models.Model):
    day = models.IntegerField()
    price = models.CharField(max_length=8)
    course_id = models.IntegerField()  
    content_type = models.ForeignKey(to=ContentType, null=True)  # Will be changed to foreign key
   # Custom operations
   # 1. Insert a strategy into course data; use _meta.model_name to get table name string
   # Method: First query course; get table name through course; insert data into policy table
   course = models.DegreeCourse.objects.first()
   contenttype = models.ContentType.objects.filter(model=course._meta.model_name).first()
   models.PricePolicy.objects.create(day=7, price=0, course_id=course.id, content_type=contenttype)


   # 2. Query policies by course
   # Method: Same as above
   course = models.DegreeCourse.objects.first()
   contenttype = models.ContentType.objects.filter(model=course._meta.model_name).first()
   price_policy = models.PricePolicy.objects.filter(course_id=course.id, content_type=contenttype).values('day', 'price')
   print(price_policy)


   # Query course via policy using apps.get_model to retrieve table class
   # Method: First query policy table; get table class via get_model; then query data in course table
   from django.apps import apps
   price_policy_obj = models.PricePolicy.objects.filter(day=7, price=0).first()
   model = apps.get_model('API', price_policy_obj.content_type.model)   # First parameter is app name, second is table name, returns table class
   course = model.objects.filter(pk=price_policy_obj.course_id)
   print(course)

3. Using ContentType Methods for Operations


Model Definiitons

from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericRelation
from django.contrib.contenttypes.fields import GenericForeignKey

class Course(models.Model):
    name = models.CharField(max_length=32)
    price_policy = GenericRelation(to='PricePolicy')
    def __str__(self):
        return self.name

class DegreeCourse(models.Model):
    name = models.CharField(max_length=32)
    price_policy = GenericRelation(to='PricePolicy')
    def __str__(self):
        return self.name

class PricePolicy(models.Model):
    day = models.IntegerField()
    price = models.CharField(max_length=8)
    object_id = models.IntegerField()
    content_type = models.ForeignKey(to=ContentType, null=True)
    model_obj = GenericForeignKey()

# Note:
#     1. model_obj refers to DegreeCourse or Course table objects
#     2. object_id refers to course ID, corresponding to parameters in GenericForeignKey
#     3. If customizing object_id and content_type, parameters in GenericForeignKey and GenericRelation must also be modified, e.g.:
#         course_id = models.IntegerField()  
#         course_type = models.ForeignKey(to=ContentType, null=True)
#         model_obj = GenericForeignKey(ct_field='course_type', fk_field='course_id')
#
#         price_policy = GenericRelation(to='PricePolicy', object_id_field='course_id', content_type_field='course_type')
# 1. Insert a strategy for course data
degree_course = models.DegreeCourse.objects.first()
models.PricePolicy.objects.create(day=180, price=18880, model_obj=degree_course)


# 2. Find all price policies for all courses
price_policy_list = models.PricePolicy.objects.all()
for price_policy in price_policy_list:
    print(price_policy.model_obj.name, price_policy.day, price_policy.price)


# 3. Query policies by course
course = models.Course.objects.first()
price_policys = course.price_policy.all()
for price_policy in price_policys:
    print(course.name, price_policy.day, price_policy.price)

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.