" name="sm-site-verification"/>
侧边栏壁纸
博主头像
PySuper博主等级

千里之行,始于足下

  • 累计撰写 203 篇文章
  • 累计创建 14 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录
Web

Django ContentTypes 框架

PySuper
2021-01-21 / 0 评论 / 0 点赞 / 13 阅读 / 6532 字
温馨提示:
所有牛逼的人都有一段苦逼的岁月。 但是你只要像SB一样去坚持,终将牛逼!!! ✊✊✊

Django Contenttypes

对于需要返回查询集的–写在QuerySetModel

模型类中数据库处理的–写在Models

业务相关逻辑的处理—写在Views

记录Django项目中,所有模型类所属的应用,以及模型类的名字

  • 对当前项目中所有给予Django驱动的model,提供了更高层次的抽象接口(models.Model,models.py
  • 方便我们动态调用模型类
  • Django权限管理中的Permission借助ContentType实现了对任意models的权限操作

GenericForeignKey

  • 不支持使用on_delete,默认就是删除级联

GenericRelation

  • ContentType的通用类型–GenericRelation(实现对所有模型类的关联操作)

业务场景

  • 多个模型类需要使用同一功能
  • 如:博客、文章、图片、想法、笔记,每个模型类里面都需要使用评论功能
from django.contrib.auth.models import User
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType  # 查看源码
from django.db import models


# 通用模型类
class Comment(models.Model):
    author = models.ForeignKey(to=User, on_delete=models.CASCADE)
    body = models.TextField(blank=True)

    # 这三个字段组合起来 ==> 实现通用模型类(app_lable、model、id)
    content_type = models.ForeignKey(ContentType, models.CASCADE)
    object_id = models.IntegerField
    content_object = GenericForeignKey()


# 再把这个模型类关联到其他的模型类中:
class Blog(models.Model):
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    body = models.TextField()
    comments = GenericRelation(Comment)  # 通用外检关联


class Article(models.Model):
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    body = models.TextField()
    comments = GenericRelation(Comment)  # 通用外检关联


class Picture(models.Model):
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    body = models.TextField()
    comments = GenericRelation(Comment)  # 通用外检关联

ContentType 的巧妙用法

Timeline设计

在首页展示不同模块的数据,按照时间排序

一般是使用个性推荐算法==> 不用用户在同一时间看到的数据是不一样的

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

# TODO: 信号量机制
from django.db.models.signals import post_save


class Index(models.Model):
    """首页--通用模型类"""
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey("content_type", "object_id")

    pub_date = models.DateTimeField(auto_now_add=True)

    class Meta:
        """
        TODO
            每当后面三个模型类中有数据生成的时候,都会在这里创建一条数据
            最后在排序的时候,使用这里的数据进行排序,就能对不同模块的数据进行排序了
        """
        ordering = ["-pub_date"]

    # TODO:问题2:如何在调用基类的时候,获取到其他三张表中的数据
    @property
    def content(self):
        return self.content_object.content


class News(models.Model):
    """动态"""
    content = models.CharField(max_length=255)
    pub_date = models.DateTimeField(auto_now_add=True)

    # index = GenericRelation(Index)  # 关联到通用模型类的表

    # TODO: 问题1 :如何在其他的模型类中,生成一条数据的时候,在基类中也创建一条数据(代码复用性)
    # def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
    #     content_type = ContentType.objects.get_or_create(self)
    #     # self.index.get_or_create(pub_data=self.pub_date)
        Index.objects.get_or_create(
            content_type=content_type, 
            object_id=self.id, 
            pub_date=self.pub_date
        )


class Article(models.Model):
    """文章"""
    title = models.TextField()
    pub_date = models.DateTimeField(auto_now_add=True)
    # index = GenericRelation(Index)

    
    # def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
    #     content_type = ContentType.objects.get_or_create(self)
    #     # self.index.get_or_create(pub_data=self.pub_date)
    #     Index.objects.get_or_create(
    #         content_type=content_type, 
    #         object_id=self.id, 
    #         pub_date=self.pub_date
    #     )


class Question(models.Model):
    """问题"""
    title = models.TextField()
    pub_date = models.DateTimeField(auto_now_add=True)
    # index = GenericRelation(Index)

    # def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
    #     content_type = ContentType.objects.get_or_create(self)
    #     # self.index.get_or_create(pub_data=self.pub_date)
    #     Index.objects.get_or_create(
    #         content_type=content_type, 
    #         object_id=self.id, 
    #         pub_date=self.pub_date
    #     )


def create_index(sender, instance, **kwargs):
    """
    这里使用信号量机制,每当完成一次创建,就关联到ContentType中创建一条数据
    sender: 发送者
    instance:实例对象
    """
    if "created" in kwargs:  # TODO: 每次创建的时候触发
        content_type = ContentType.objects.get_for_model(instance)
        Index.objects.get_or_create(
            content_type=content_type, 
            object_id=instance.id, 
            pub_date=instance.pub_date
        )


# 固定写法
post_save.connect(create_index, sender=News)
post_save.connect(create_index, sender=Article)
post_save.connect(create_index, sender=Question)
0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区