DRF框架---查漏补缺要趁早

1. Django数据库中的F和Q对象操作:

# F对象:查询时字段之间的比较
 from django.db.models import F, Sum
 # 查询阅读量大于评论量的图书
 books = Book.objects.filter(bread__gt=F("bcomment"))
 # 查询阅读量大于2倍评论量的图书(可以在F对象上使用算数运算)
 books = Book.objects.filter(bread__gt=F("bcomment")*2)
 # Q对象,用于多个条件之间逻辑判断 且& 或| 非~
  from django.db.models import Q
    
 # Q对象,查询阅读量大于20,并且编号小于3的图书
 books = Book.objects.filter(bread__gt=20, id__lt=3)
 books = Book.objects.filter(Q(bread__gt=20) & Q(id__lt=3))
 # 查询阅读量大于20,或编号小于3的图书
 books = Book.objects.filter(Q(bread__gt=20) | Q(id__lt=3))
 # 查询编号不等于3的图书
 books = Book.objects.filter(~Q(id=3))

  在查询对象时,使用get(column)和fliter(column)的区别是:

  当对象不存在时,get会返回异常DoesNotExist,filter会返回空;对象存在时,两者一样。

2. Django数据库中的聚合函数操作:

   使用aggregate()过滤器调用聚合函数,返回字典类型,如 {'属性名__聚合类小写': 值},{'users__sum':3}

# 定义聚合函数
from django.db.models import Count, Sum, Avg, Max, Min
    
# 查询图书的总阅读量
books = Book.objects.aggregate(Sum('bread'))    # {'bread__sum': 136}
# 查询图书总数(使用count时一般不使用aggregate()过滤器, 注意count函数的返回值是一个数字)
books = Book.objects.count()
books = Book.objects.aggregate(Count('id'))     # {'id__count': 5}
# 排序  使用order_by对结果进行排序
# 对所有图书按照阅读量从小到大排序 > 升序
books = Book.objects.order_by('bread')
    
# 对所有图书按照阅读量从大到小排序 > 降序
books = BookInfo.objects.order_by('-bread')

3. django_filters查询插件的使用:

class FlowInfoFilter(django_filters.FilterSet):
    start_time = django_filters.IsoDateTimeFilter(name='stat_time', lookup_expr='gte')
    end_time = django_filters.IsoDateTimeFilter(name='stat_time', lookup_expr='lte')
    interface = django_filters.NumberFilter(name="interface", method="interface_filter")
    src_ip = django_filters.CharFilter(name="src_ip", lookup_expr='exact')
    dst_as = django_filters.NumberFilter(name="dst_as", lookup_expr='exact')
    bgp_route = django_filters.CharFilter(name="bgp_route", lookup_expr='contains')

    def interface_filter(self, queryset, key, value):
        return queryset.filter(Q(input_inf=value) | Q(output_inf=value))
   
    class Meta:
        model = FlowInfo
        fields = ['stat_time', 'input_inf', 'output_inf', 'src_ip', 'dst_as', 'bgp_route']

该类的解释:

     model:该类是为Model FlowInfo定义的过滤类

     fields:该过滤类可以处理FlowInfo中字段为stat_time,src_ip,dst_as,bgp_route的查询

     name = django_filters.CharField(name='xxx', lookup_expr='contains')指定name字段的过滤条件为contains

其中,CharFilter/NumberFilter/BooleanFilter/DateFilter/UUIDFilter/TimeFilter/DateTimeFilter/ChoiceFilter/RangeFilter等是过滤参数的类型,name为筛选的参数名,需要和model中定义的一致,可省略,省略后和字段名保持一致;lookup_expr为筛选参数的条件,icontains为忽略大小写模糊查询,gte为大于等于,gt为大于,lte为小于等于,lt为小于,exact为等于,lookup_expr可省略,表示exact;method表示要筛选的字段需要做一些复杂的处理,就指定一个方法名,通过是实现方法来完成复杂查询。

4. 数据列表导出成csv或其他格式时,直接打开文件中文会显示乱码,用编辑器如Notepad++就是正常的,这是因为在导出时默认格式为UTF-8 with BOM(Byte Order Mark),这时,就需要在代码里面将BOM去掉,可以使用codecs模块。codecs提供的方法可以指定一个编码打开文件,使用这个方法打开的文件读取返回的将是unicode。写入时,如果参数是unicode,则使用open()时指定的编码进行编码后写入;如果是str,则先根据源代码文件声明的字符编码,解码成unicode后再进行前述 操作。相对内置的open()来说,这个方法不容易在编码上出现问题。所以,推荐大家在文件读写的时候使用codecs。

import codecs
with open(config_path) as source_file:
    data = source_file.read()
    
   # 去掉BOM
   if data[:3] == codecs.BOM_UTF8:  # 判断是否为带BOM文件
        data = data[3:]
        with codecs.open(config_path) as dest_file:
            dest_file.write(data)

当然也可以简便一些,直接使用如下语句打开文件:

with codecs.open(file_name, 'w', 'utf-8-sig') as tmp_file

utf-8-sig中sig为signature,也就是带有签名的utf-8,因此在读取文件时,会把BOM单独处理,与文本内容隔离开。

5. 在定义或查询数据库字段,有时我们会希望将字段类型设置为json格式,方便我们展示和处理。这时,数据库中的model使用

    name = models.CharField(max_length=120)

    序列化器

    name = serializers.JSONFiled()

    但是DRF框架的JSONField字段返回的是字符串,并且保存到数据库中的数据也转成了Python的数据格式,字典里面的键用单引号,但是一般的json格式都是用双引号,无论前端还是后端解释都无法正常显示,所以我们需要修改下JSONField的实现:

# -*- coding:utf-8 -*-
"""
扩展django的Field
"""
import json
from django.db import models
class JSONField(models.TextField):
    def to_python(self, value):
        if isinstance(value, list):
            return value
        else:
            return json.loads(value)
    def get_prep_value(self, value):
        return json.dumps(value)

6. 有时,我们希望数据库存储的字段类型为list,这时,也需要去改造相应的model和序列化器:

from django.db import models
from django.contrib.postgres.fields import ArrayField
class XXX(models.Model):
    name = ArrayField(models.CharField(max_length=1000), default=[], verbose_name="xxx")



from rest_framework import serializers
class XXXSerializer(serializers.ModelSerializer):
     name= serializers.ListField(default=[])

 通过如上修改,就会使得数据库存储的字段和读出的字段都是字符串数组格式。

7. 数据库经常会有一些整型字段需要校验,下拉列表字段需要判断是否合法,这时就可以使用Django自带的快捷校验,而不需要在单独写一个validate方法:

from django.db import models
from django.utils import timezone
from django.core.validators import MinValueValidator
from django.core.validators import MaxValueValidator
TYPES = [
    (1, '地理'),
    (2, '历史'),
    (3, '语文'),
    (4, '英语')
]
class XXX(models.Model):
    address = models.GenericIPAddressField() # 默认支持ipv4,ipv6
    as_num = models.BigIntegerField(validators=[MinValueValidator(1),MaxValueValidator(4294967295)])  # 校验AS范围
    create_time = models.DateTimeField(default=timezone.now) # 创建时间为当前数据插入时间  
    object_type = models.CharField(max_length=20, choices=TYPES)  # 下拉选项

8. 有时我们会去求两个数组之间的交集、并集和差集:

a = [2, 3, 4, 5]
b = [2, 5, 8]
# 交集
print (list(set(a).intersection(set(b))))   # [2, 5]
# 并集
print (list(set(a).union(set(b)))) # [2, 3, 4, 5, 8]
# 差集(a中有而b中没有的)
print (list(set(a).difference(set(b)))) #[3, 4] 

 

你可能感兴趣的:(Django,REST,Framework,Python)