"/>
侧边栏壁纸
博主头像
PySuper 博主等级

千里之行,始于足下

  • 累计撰写 218 篇文章
  • 累计创建 15 个标签
  • 累计收到 2 条评论

目 录CONTENT

文章目录
Web

Django--模型类、序列化器

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

自定义模型基类

  • 项目中的模型,继承自BaseEntity可以继承这些常用字段

  • 结合自定义的序列化器,可以直接序列化所有基础字段

  • 提供了常用的方法,如__str__removerestore

  • 这里的name字段,有些自类中不需要,就直接写name = None,再重写__str__方法

class BaseEntity(models.Model):
    """
    抽象基类,用于提供创建人、更新时间等公共字段
    """

    # name = None
    update_date = models.DateTimeField(auto_now=True, verbose_name="更新时间")
    status = models.BooleanField(default=True, editable=False, verbose_name="状态")
    del_flag = models.BooleanField(default=False, editable=False, verbose_name="删除")
    remark = models.CharField(max_length=500, null=True, blank=True, verbose_name="备注")
    name = models.CharField(max_length=50, unique=True, blank=True, null=True, verbose_name="名称")
    code = models.CharField(max_length=50, unique=True, blank=True, null=True, verbose_name="编码")
    create_date = models.DateTimeField(auto_now_add=True, editable=False, db_index=True, verbose_name="创建时间")
    create_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        null=True,
        on_delete=models.SET_NULL,
        verbose_name="创建人",
        related_name="%(class)s_created",
    )
    update_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        null=True,
        on_delete=models.SET_NULL,
        verbose_name="更新人",
        related_name="%(class)s_updated",
    )

    class Meta:
        ordering = ["-id"]  # 默认按 ID 降序排列
        abstract = True  # 声明为抽象类,不会在数据库中创建表

    def __str__(self):
        """默认就是name,不是name的就自定义"""
        return self.name

    def remove(self):
        """标记对象为已删除"""
        self.del_flag = True
        self.save()

    def restore(self):
        """恢复被标记为已删除的对象"""
        self.del_flag = False
        self.save()

    def __init_subclass__(cls, **kwargs):
        """动态设置Meta选项"""
        super().__init_subclass__(**kwargs)
        if not hasattr(cls, "Meta"):

            class Meta:
                ordering = ["id"]
                verbose_name = cls.__name__
                verbose_name_plural = cls.__name__

            cls.Meta = Meta
        else:
            if not hasattr(cls.Meta, "verbose_name"):
                cls.Meta.verbose_name = cls.__name__
            if not hasattr(cls.Meta, "verbose_name_plural"):
                cls.Meta.verbose_name_plural = cls.__name__

这里也可以使用元类,动态设置Meta选项

class DynamicMeta(type):
    """
    元类,用于动态设置Meta选项
    """

    def __new__(cls, name, bases, attrs):
        # 创建类时动态设置Meta选项
        if "Meta" not in attrs:

            class Meta:
                ordering = ["id"]
                verbose_name = name
                verbose_name_plural = name

            attrs["Meta"] = Meta
        else:
            # 如果Meta类已经存在,动态设置verbose_name和verbose_name_plural
            attrs["Meta"].verbose_name = name
            attrs["Meta"].verbose_name_plural = name
        return super().__new__(cls, name, bases, attrs)

class BaseEntity(models.Model, metaclass=DynamicMeta):
    # 其他代码不变
    pass

自定义序列器

  • 自定义序列化器基类,用于序列化 BaseEntity 中的公共字段

  • 同样可以写具体字段的取值方法

class BaseSerializer(serializers.ModelSerializer):
    """
    自定义序列化器基类,用于序列化 BaseEntity 中的公共字段
    """

    def to_representation(self, instance):
        """重写返回值中的公共字段"""
        res = super().to_representation(instance)
        # 这里直接用instance,就不需要序列化器中增加这个字段
        res["createBy"] = instance.username if instance.create_by else None
        res["updateBy"] = instance.username if instance.update_by else None
        # 格式化时间:年月日 时分秒
        res["createTime"] = instance.create_date.strftime("%Y-%m-%d")
        res["updateTime"] = instance.update_date.strftime("%Y-%m-%d")
        # 当前对象的状态
        res["status"] = "1" if res.pop("status") else "2"
        # 自定义返回的字段
        return res

结合使用

模型类

  • 只定义几个字段,但继承自BaseEntity, AbstractUser,就有很多基础字段可以用

  • 不使用name字段,就用None覆盖,同时重写__str__方法

  • BaseEntity父类中使用__init_subclass__方法设置了Meta类,这里就不用再写 class Meta 了

class User(BaseEntity, AbstractUser):
    """用户模型类"""

    GENDERS = [(1, "男"), (2, "女")]
    name = None  # 覆盖name字段,使其不可用
    phone = models.CharField(max_length=11, null=True, blank=True, verbose_name="电话")
    gender = models.PositiveIntegerField(choices=GENDERS, default=1, verbose_name="性别")
    nick_name = models.CharField(max_length=150, null=True, blank=True, verbose_name="用户昵称")
    position = models.CharField(max_length=20, choices=settings.USER_TYPE, default="student", verbose_name="职位")

    def __str__(self):
        return self.username

序列化

  • 继承自BaseSerializer,已经对基础字段序列化了,不需要再处理

  • 如果有额外要添加的字段,如roles,可以使用函数等方式获取

class UserListSerializer(BaseSerializer):
    """
    公共users列表序列化
    """
    
    roles = serializers.SerializerMethodField()
    
    class Meta:
        model = User
        fields = ["id", "username", "phone", "email", "position"]

    def get_roles(self, obj):
        return list(obj.roles.values_list("id", flat=True))

其他序列化

树结构

# 自定义树形结构序列化器
class TreeSerializer(Serializer):
    """
    自定义树形结构序列化器
    """

    id = serializers.IntegerField()  # 节点ID
    label = serializers.CharField(max_length=20, source="name")  # 节点名称
    pid = serializers.PrimaryKeyRelatedField(read_only=True)  # 父节点ID

自定义健值

# 自定义返回键值对的序列化器
class ResKeySerializer(serializers.Serializer):
    """自定义返回键值对的序列化器"""

    def to_representation(self, instance):
        representation = super().to_representation(instance)
        representation["createBy"] = instance.create_by.username if instance.create_by else ""
        representation["createTime"] = representation.pop("create_date", None)
        representation["updateBy"] = instance.update_by.username if instance.update_by else ""
        representation["updateTime"] = representation.pop("update_date", None)
        representation["status"] = "1" if instance.del_flag else "2"
        return representation

过滤删除

# 过滤掉所有标记为已删除的对象(即 del_flag=True 的对象)
class DeletedFilterListSerializer(ListSerializer):

    """
    使用:确保在批量查询时,自动过滤掉已删除的对象
    class MyModelSerializer(serializers.ModelSerializer):

    class Meta:
        model = MyModel
        fields = '__all__'
        list_serializer_class = DeletedFilterListSerializer
    """

    def to_representation(self, data):
        """
        过滤掉所有标记为已删除的对象(即 del_flag=True 的对象),只返回 del_flag=False 的数据
        主要用处在于对查询结果进行数据筛选,以便在序列化时自动排除被逻辑删除的对象
        :param data:
        :return:
        """
        data = data.filter(del_flag=False)
        return super(DeletedFilterListSerializer, self).to_representation(data)

1
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区