自定义模型基类
项目中的模型,继承自
BaseEntity
可以继承这些常用字段结合自定义的序列化器,可以直接序列化所有基础字段
提供了常用的方法,如
__str__
、remove
、restore
这里的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)
评论区