17.Django学习之django自带的contentType表

    通过django的contentType表来搞定一个表里面有多个外键的简单处理: 摘自:https://blog.csdn.net/aaronthon/article/details/81714496

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

    models.py文件的表结构写好后,通过makemigrations和migrate两条命令迁移数据后,在数据库中会自动生成一个django_content_type表,比如我们有在models.py中写了这么几张表:

from django.db import models

class Electrics(models.Model):
    """
    id    name
     1   日立冰箱
     2   三星电视
     3   小天鹅洗衣机
    """
    name = models.CharField(max_length=32)

class Foods(models.Model):
    """
    id   name
    1    面包
    2    烤鸭
    """
    name = models.CharField(max_length=32)

class Clothes(models.Model):
    name = models.CharField(max_length=32)

class Coupon(models.Model):  # 特殊关系表
"""
  id    name    electric_id   food_id   cloth_id   more...   # 每增加一张表,关系表的结构就要多加一个字段。
    1   通用优惠券   null       null      null
    2   冰箱满减券   2         null     null
    3   面包狂欢节   null        1      null
"""
name = models.CharField(max_length=32)
electric = models.ForeignKey(to='Electrics', null=True)
food = models.ForeignKey(to='Foods', null=True)
cloth = models.ForeignKey(to='Clothes', null=True)

    

      

    

    

  如果是通用优惠券,那么所有的ForeignKey为null,如果仅限某些商品,那么对应商品ForeignKey记录该商品的id,不相关的记录为null。但是这样做是有问题的:实际中商品品类繁多,而且很可能还会持续增加,那么优惠券表中的外键将越来越多,但是每条记录仅使用其中的一个或某几个外键字段。

  contenttypes 应用

    通过使用contenttypes 应用中提供的特殊字段GenericForeignKey,我们可以很好的解决这个问题。只需要以下三步:

    在model中定义ForeignKey字段,并关联到ContentType表。通常这个字段命名为“content_type”

    在model中定义PositiveIntegerField字段,用来存储关联表中的主键。通常这个字段命名为“object_id”

    在model中定义GenericForeignKey字段,传入上述两个字段的名字。

    为了更方便查询商品的优惠券,我们还可以在商品类中通过GenericRelation字段定义反向关系。

  示例代码:models.py文件:

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

class Electrics(models.Model):
    name = models.CharField(max_length=32)
    price = models.IntegerField(default=100)
    coupons = GenericRelation(to='Coupon')  # 用于反向查询,不会生成表字段

    def __str__(self):
        return self.name

class Foods(models.Model):
    name = models.CharField(max_length=32)
    price=models.IntegerField(default=100)
    coupons = GenericRelation(to='Coupon')

    def __str__(self):
        return self.name

class Clothes(models.Model):
    name = models.CharField(max_length=32)
    price = models.IntegerField(default=100)
    coupons = GenericRelation(to='Coupon')

    def __str__(self):
        return self.name

class bed(models.Model):
    name = models.CharField(max_length=32)
    price = models.IntegerField(default=100)
    coupons = GenericRelation(to='Coupon')

class Coupon(models.Model):
    """
    Coupon
        id    name                      content_type_id       object_id_id
              美的满减优惠券                    9(电器表electrics)   3
              猪蹄买一送一优惠券                10                    2
              南极被子买200减50优惠券           11                    1
    """
    name = models.CharField(max_length=32)

    content_type = models.ForeignKey(to=ContentType,on_delete=models.CASCADE) # step 1 既然没有直接和关联表进行外键关系,我们通过这一步先找到关联表
    object_id = models.PositiveIntegerField() # step 2  #存的是关联的那个表的对应的那条记录的id
    content_object = GenericForeignKey('content_type', 'object_id') # step 3  对象.content_object直接就拿到了这个优惠券对象关联的那个商品记录对象。

    def __str__(self):
        return self.name

  注意:ContentType只运用于1对多的关系!!!并且多的那张表中有多个ForeignKey字段。

  数据化迁移,再给每张表添加数据

  衣服表,电器表,床上用品表,美食表

  添加完之后,数据迁移,python manage.py makemigrations 和 python manage.py migrate

创建记录和查询

from django.shortcuts import render, HttpResponse
from api import models
from django.contrib.contenttypes.models import ContentType

def test(request):
    if request.method == 'GET':
        # ContentType表对象有model_class() 方法,取到对应model
        content = ContentType.objects.filter(app_label='api', model='electrics').first()  # 表名小写
        cloth_class = content.model_class() # cloth_class 就相当于models.Electrics
        res = cloth_class.objects.all()
        print(res)

        # 为三星电视(id=2)创建一条优惠记录
        s_tv = models.Electrics.objects.filter(id=2).first()
        models.Coupon.objects.create(name='电视优惠券', content_object=s_tv)

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

        # 查询三星电视(id=2)的所有优惠券
        res = s_tv.coupons.all()
        print(res)

  

  总结: 当一张表和多个表FK关联,并且多个FK中只能选择其中一个或其中n个时,可以利用contenttypes app,只需定义三个字段就搞定!

  创建记录

    关系表的结构

    

  用语法给关系表加记录。

  添加方式1:

    

    

    

  接下来用postmen来发送请求

    

  然后代金券表数据就添加完成了

    

  添加方式2:

    

  通过postmen发送请求结果

    

  查询记录

  查询name="电商1代金券"的代金券信息

    

    

原文地址:https://www.cnblogs.com/changxin7/p/12033148.html

时间: 2024-11-09 02:55:19

17.Django学习之django自带的contentType表的相关文章

Django学习之django自带的contentType表

Django学习之django自带的contentType表 通过django的contentType表来搞定一个表里面有多个外键的简单处理: 摘自:https://blog.csdn.net/aaronthon/article/details/81714496 contenttypes 是Django内置的一个应用,可以追踪项目中所有app和model的对应关系,并记录在ContentType表中. models.py文件的表结构写好后,通过makemigrations和migrate两条命令

[django学习0-1] django + eclipse基本环境

1.安装django 如果还没有安装python需要先安装python,django1.6对2.6,2.7,3.2或3.3都支持了,这里用的是python2.7.8 然后安装django,发布版本已更新至1.6.6,下载在https://www.djangoproject.com/ (如果已安装旧版需要先删掉旧版) 安装方法win下,先解压django包,然后运行python setup.py install 等待安装完就可以了(需要先设置python环境变量,setup.py在django解压

django 学习-15 Django会话Cookie

1.django.admin.py  startproject   cs3 cd cs3 django.admin.py   startapp   blog 2.    vim urls.py url(r'^regist/$','blog.views.regist'),       注册    url(r'^login/$','blog.views.login'), 登录    url(r'^index/$','blog.views.index'),      跳转界面    url(r'^lo

django 学习-11 Django模型数据模板呈现

1.for author in Author.objects.all(): for book in author.book_set.all(): print   book 2.vim blog/views.py from blog.models  import Author,Book from  django.shortcuts   import  render_to_response def show_author(req): authors = Author.objects.all() re

django 学习-14 Django文件上传 (Admin后台)

1.这种上传方式是用admin后台完成的,用数据库和model做 vim settings.py MEDIA_ROOT = '/headImg/'                                   文件保存在路径(还有后续) #   'django.middleware.csrf.CsrfViewMiddleware',            禁掉这个,跨站不会出问题 'django.contrib.admin',                                

Django 学习之Django Rest Framework(DRF)

一. WEB应用模式 在开发Web应用中,有两种应用模式 1. 前后端不分离 2. 前后端分离 二. API接口 为了在团队内部形成共识.防止个人习惯差异引起的混乱,我们需要找到一种大家都觉得很好的接口实现规范,而且这种规范能够让后端写的接口,用途一目了然,减少双方之间的合作成本. 目前市面上大部分公司开发人员使用的接口服务架构主要有:restful.rpc. 1. rpc rpc: 翻译成中文:远程过程调用[远程服务调用]. http://www.example.com/api post请求

Django学习之Django shell

Django shell交互式,方便调试,开发. python manage.py shell from blog.models import Article a=Article() a.title='title' a.brief_content='brief_content' a.content='content' a.save() print (a) articles=Article.objects.all() article=articles[0] print(article.title)

Django学习之Django admin

1.后台管理工具 2.读取定义的模型数据 3.Django shell 新增文章复杂,在后台简单方便(编辑,开发,删除) 4.认证用户,显示管理模型,检验输入等功能 5.使用: 第一步 创建管理员用户 python manage.py createsuperuser 启动服务: python manage.py runserver 第二步 页面登陆,管理模型数据: 第三步:注册模型到admin里面 刷新页面: 可知三篇文章都是Article object不好区分,所以开发区分: 至此,admin

django 学习-10 Django多对多关系模型

1.vim blog/models.py class   Author(models.Model): name = models.CharField(max_length=30) def unicode(self): return self.name class Book(models.Model): name = models.CharField(max_length=30) authors = models.ManyToMany(Author) def unicode(self): retu