查询优化
- 一对一,一对多使用select_related();多对一,多对多,使用prefetch_related()。这个根据字段的关系封装在DRF的Serializer里面,得到最终queryset后,在进行select_related() / prefetch_related() 操作即可。
- 只获取使用的字段,不要把所有字段都取出来,使用queryset.values() queryset.values_list(),前者返回dict,后者返回list
- queryset.defer(),延迟加载某些字段的数据,直到访问它们为止。有一种例外,如果只传一个None参数,会删除所有延迟加载
- queryset.only(),与defer相反,传入该方法的字段,在queryset被evaluate时会立即加载这些字段的数据。
- 如果有条件或者对效率要求高的话,自己序列化Model,不要使用DRF;但是DRF实现很多很实用很方便的功能,如果要自己实现的话会很麻烦,其中的利弊只能自己权衡了。
queryset何时被evaluate(不知道如何翻译,只能用原文了)
- Iteration
- Slicing
- Pickling/Caching
- repr()
- len()
- list()
- 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使用方式类似。
待补充