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]