django -- ContentType

前戏

假设现在我们有很多张表,比如Food表,Fruit表等等。有一天这些东西都要打折,那我们要新建一张表,里面写的打折信息,要把所有的表都关联在一起,这样的话就会在一张表里有很多的外键,例如下面的。

from django.db import models

class Food(models.Model):
    """
    id    name
    1     麻婆豆腐
    2     木耳炒牛肉
    3     西红柿炒鸡蛋
    """
    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    title           food_id   fruit_id  ..........
    1    麻婆豆腐买一送一     1         null
    2     香蕉2折          null        2
    """
    title = models.CharField(max_length=32)
    food = models.ForeignKey(to="Food")
    fruit = models.ForeignKey(to="Fruit")

优化表结构

既然一张表里有这么多的外键,那我们可不可以新建一张表,专门用来存放app和表名的,如下

from django.db import models

class Food(models.Model):
    """
    id    name
    1     麻婆豆腐
    2     木耳炒牛肉
    3     西红柿炒鸡蛋
    """
    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    title           food_id   fruit_id  ..........
    1    麻婆豆腐买一送一     1         null
    2     香蕉2折          null        2
    """
    title = models.CharField(max_length=32)
    table = models.ForeignKey(to="MyTables")
    object_id = models.IntegerField()

class MyTables(models.Model): """ id app_name table_name 1 Demo Food 2 Demo Fruit """ app_name = models.CharField(max_length=32) table_name = models.CharField(max_length=32)

Mytables表里存放了我们所有的app名和表名,在Coupon表里通过外键关系关联到MyTables表,这样就解决了一张表里多个外键的问题

ContentType

Django在生成数据表的时候已经给我们提供了这张表“MyTables”,表名叫content_type,里面的字段含义和我们自定义的一样

django -- ContentType

 

 所以第三张表就不用我们自己创建了,直接使用Django自带的就可以了

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



class Food(models.Model):

    name = models.CharField(max_length=32)
    # 不生成字段只用于反向查询
    coupons = GenericRelation(to="Coupon")


class Fruit(models.Model):
 
    name = models.CharField(max_length=32)
    coupons = GenericRelation(to="Coupon")


class Coupon(models.Model):
   
    title = models.CharField(max_length=32)
    content_type = models.ForeignKey(to=ContentType)
    object_id = models.IntegerField()
    # 不会生成字段 只用于关联到对象的
    content_object = GenericForeignKey("content_type", "object_id")

使用ORM添加数据

from django.shortcuts import render
from rest_framework.views import APIView
from django.http import HttpResponse
from .models import Food, Fruit, Coupon
from django.contrib.contenttypes.models import ContentType


class TestView(APIView):
    def get(self, request):
        # 找到表id以及表对象
        food_obj = Food.objects.filter(id=1).first()
        # 往Coupon表里插数据
        Coupon.objects.create(title="水密桃大甩卖", content_object=food_obj)
        return HttpResponse("ok")

查询数据

from django.shortcuts import render
from rest_framework.views import APIView
from django.http import HttpResponse
from .models import Food, Fruit, Coupon
from django.contrib.contenttypes.models import ContentType


class TestView(APIView):
    def get(self, request):
        # 查询出来的是Food或者Fruit对象
        coupon_obj = Coupon.objects.filter(id=1).first()
        # 通过content_object.name拿到对应的name值
        print(coupon_obj.content_object.name)
        # 查某个对象的优惠券
        food_obj = Food.objects.filter(id=1).first()
        print(food_obj.coupons.all())
        return HttpResponse("ok")

 

上一篇:restful接口规范


下一篇:为啥 Response.Write 后,View就不渲染了?