Django的ContentType组件

需求

我们商城里有很多的商品,节日要来了,我们要搞活动

那么我们就要设计优惠券,优惠卷都有什么类型嗯,满减的,折扣的,立减的等

我们对应着我们活动类型,对我们的某类商品设计优惠券,

比如:

家电是一类商品
食物是一类商品
那么我们可以设计家电折扣优惠卷,以及食物满减优惠卷等

那么表结构怎么设计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

from django.db import models


class Appliance(models.Model):
"""
家用电器表
id name
1 冰箱
2 电视
3 洗衣机
"""
name = models.CharField(max_length=64)


class Food(models.Model):
"""
食物表
id name
1 面包
2 牛奶
"""
name = models.CharField(max_length=32)


class Fruit(models.Model):
"""
水果表
id name
1 苹果
2 香蕉
"""
name = models.CharField(max_length=32)


class Coupon(models.Model):
"""
优惠券表
id name appliance_id food_id fruit_id
1 通用优惠券 null null null
2 冰箱折扣券 1 null null
3 电视折扣券 2 null null
4 苹果满减卷 null null 1
我每增加一张表就要多增加一个字段
"""
name = models.CharField(max_length=32)
appliance = models.ForeignKey(to="Appliance", null=True, blank=True)
food = models.ForeignKey(to="Food", null=True, blank=True)
fruit = models.ForeignKey(to="Fruit", null=True, blank=True)<br># 实际上我们商品的种类会特别的多,导致我们这张表外键越来越多

遇到这种一张表要跟多张表进行外键关联的时候,我们的Django提供了ContentType组件

ContentType组件

ContentType是Django内置的一个应用,可以追踪项目中所有的APP和model的对应关系,
并且记录在ContentType表中。

当我们的项目做数据库迁移后,会有很多DJango自带的表,其中就有dJango_content_type表

ContentType组件应用

1,在model中定义ForeignKey字段,并关联到ContentType表,通常这个字段命名为content-type
2,在model中定义PositiveIntergerField字段, 用来存储关联表中的主键,通常我们用object_id
3,在model中定义GenericForeignKey字段,传入上面两个字段的名字
4,方便反向查询可以定义GenericRelation字段

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation


class Appliance(models.Model):
"""
家用电器表
id name
1 冰箱
2 电视
3 洗衣机
"""
name = models.CharField(max_length=64)
coupons = GenericRelation(to="Coupon")


class Food(models.Model):
"""
食物表
id name
1 面包
2 牛奶
"""
name = models.CharField(max_length=32)


class Fruit(models.Model):
"""
水果表
id name
1 苹果
2 香蕉
"""
name = models.CharField(max_length=32)


class Coupon(models.Model):
"""
优惠券表
id name appliance_id food_id fruit_id
1 通用优惠券 null null null
2 冰箱折扣券 1 null null
3 电视折扣券 2 null null
4 苹果满减卷 null null 1
我每增加一张表就要多增加一个字段
"""
name = models.CharField(max_length=32)
# appliance = models.ForeignKey(to="Appliance", null=True, blank=True)
# food = models.ForeignKey(to="Food", null=True, blank=True)
# fruit = models.ForeignKey(to="Fruit", null=True, blank=True)
# 第一步
content_type = models.ForeignKey(to=ContentType)
# 第二步
object_id = models.PositiveIntegerField()
# 第三步
content_object = GenericForeignKey('content_type', 'object_id')

数据库迁移后,添加数据,再进行增删改操作

基本的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
from django.http import HttpResponse
from rest_framework.views import APIView
from rest_framework.response import Response
from django.contrib.contenttypes.models import ContentType
from .models import Appliance, Coupon

# Create your views here.


class Test(APIView):

def get(self, request):
# 通过ContentType获得表名
content = ContentType.objects.filter(app_label="app01", model="appliance").first()
# 获得表model对象 相当于models.Applicance
model_class = content.model_class()
ret = model_class.objects.all()

# 为海尔冰箱创建一条优惠记录
ice_box = Appliance.objects.filter(id=1).first()
Coupon.objects.create(name="海尔冰箱折扣券", content_object=ice_box)

# 查询优惠券id=1绑定了哪个商品
coupon_obj = Coupon.objects.filter(id=1).first()
goods_obj = coupon_obj.content_object
print(goods_obj.name)

# 查询海尔冰箱的所有优惠券 id=1
# 我们定义了反向查询
results = ice_box.coupons.all()
print(results[0].name)

# 如果没定义反向查询
content = ContentType.objects.filter(app_label="app01", model="appliance").first()
result = Coupon.objects.filter(content_type=content, object_id=1).all()
print(result[0].name)
return HttpResponse(ret)
感谢您的支持!学如逆水行舟,不进则退!