django 随记

本文介绍了Django的查询优化策略,如select_related()、prefetch_related()以及values()和values_list()的使用。此外,讨论了queryset何时被evaluate的情况,如迭代、切片等,并建议在需要时自定义Manager。还分享了如何在DRF中实现动态字段序列化和Serializer的高效利用,例如动态选择序列化字段和处理JSON数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

查询优化

  1. 一对一,一对多使用select_related();多对一,多对多,使用prefetch_related()。这个根据字段的关系封装在DRF的Serializer里面,得到最终queryset后,在进行select_related() / prefetch_related() 操作即可。
  2. 只获取使用的字段,不要把所有字段都取出来,使用queryset.values()  queryset.values_list(),前者返回dict,后者返回list
  3. queryset.defer(),延迟加载某些字段的数据,直到访问它们为止。有一种例外,如果只传一个None参数,会删除所有延迟加载
  4. queryset.only(),与defer相反,传入该方法的字段,在queryset被evaluate时会立即加载这些字段的数据。
  5. 如果有条件或者对效率要求高的话,自己序列化Model,不要使用DRF;但是DRF实现很多很实用很方便的功能,如果要自己实现的话会很麻烦,其中的利弊只能自己权衡了。

queryset何时被evaluate(不知道如何翻译,只能用原文了)

  1. Iteration
  2. Slicing
  3. Pickling/Caching
  4. repr()
  5. len()
  6. list()
  7. bool()

另,如果想判断queryset是否有东西,请使用queryset.exists(),这样更有效率

自定义Manager

有时候你想把所有的查询都默认添加一个条件,这个时候你就可以考虑自定一个Manager

class FilterManager(models.Manager):
    """
    """
    def all(self):
        return self.get_queryset()

    def get_queryset(self):
        return super(FilterManager, self).get_queryset().filter(is_delete=0)

然后在Model中定义

objects = FilterManager()

这样你指定的Model在查询时,都会默认加入is_delete=0这个条件

使用DRF - 动态字段

如果你使用了DRF(django rest framework),有些东西可能会使用简化你的代码

动态字段序列化,从官网搬运过来的:

class DynamicFieldsModelSerializer(serializers.ModelSerializer):
    """
    A ModelSerializer that takes an additional `fields` argument that
    controls which fields should be displayed.
    """

    def __init__(self, *args, **kwargs):
        # Don't pass the 'fields' arg up to the superclass
        fields = kwargs.pop('fields', None)

        # Instantiate the superclass normally
        super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs)

        if fields is not None:
            # Drop any fields that are not specified in the `fields` argument.
            allowed = set(fields)
            existing = set(self.fields)
            for field_name in existing - allowed:
                self.fields.pop(field_name)

如何使用呢?

class UserSerializer(DynamicFieldsModelSerializer):
    class Meta:
        model = User
        fields = '__all__'


UserSerializer(user, fields=('id', 'email'))

这样就不需要写不同的Serializer来获取的不同字段了

使用DRF - Serializer的好用之处

Serializer的有个四个方法非常好用:
udpate:略
create:略
to_representation:读,序列化的时候按照自己的需求重新处理下数据
to_internal_value:写,按自己的需求重组数据存入数据库

举例,先定义

class JsonSerialize(serializers.Serializer):
    def update(self, instance, validated_data):
        pass

    def create(self, validated_data):
        pass

    def to_representation(self, value):
        return eval(value)

    def to_internal_value(self, data):
        pass

使用:

class TestSerialize(serializers.ModelSerializer):
    ...
    info = JsonSerialize()
    ...

    class Meta:
        model = Test
        fields = '__all__'

以JSON格式存入数据库的时候,其实是一个string类型的数据,所以取出来序列化后的数据其实还是string

所以我们这里重写了to_representation方法,把对应字段(此例中是Test Model中的info字段)的值进行eval操作,转化成json/dict,这样序列化完成后的数据就能直接以字典方式来操作了, to_internal_value使用方式类似。

待补充

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值