Django之model操作(续)

Django中的源码续

##################################################
# PUBLIC METHODS THAT RETURN A QUERYSET SUBCLASS #
##################################################
 
def raw(self, raw_query, params=None, translations=None, using=None):
    # 执行原生SQL
    models.UserInfo.objects.raw('select * from userinfo')
 
    # 如果SQL是其他表时,必须将名字设置为当前UserInfo对象的主键列名
    models.UserInfo.objects.raw('select id as nid from 其他表')
 
    # 为原生SQL设置参数
    models.UserInfo.objects.raw('select id as nid from userinfo where nid>%s', params=[12,])
 
    # 将获取的到列名转换为指定列名
    name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'}
    Person.objects.raw('SELECT * FROM some_other_table', translations=name_map)
 
    # 指定数据库
    models.UserInfo.objects.raw('select * from userinfo', using="default")
 
    ################### 原生SQL ###################
    from django.db import connection, connections
    cursor = connection.cursor()  # cursor = connections['default'].cursor()
    cursor.execute("""SELECT * from auth_user where id = %s""", [1])
    row = cursor.fetchone() # fetchall()/fetchmany(..)
 
 
def values(self, *fields):
    # 获取每行数据为字典格式
 
def values_list(self, *fields, **kwargs):
    # 获取每行数据为元祖
 
def dates(self, field_name, kind, order='ASC'):
    # 根据时间进行某一部分进行去重查找并截取指定内容
    # kind只能是:"year"(年), "month"(年-月), "day"(年-月-日)
    # order只能是:"ASC"  "DESC"
    # 并获取转换后的时间
        - year : 年-01-01
        - month: 年-月-01
        - day  : 年-月-日
    下面这句话就会截取到日,即年月日,如果填写的是year,则只会取到年
    models.DatePlus.objects.dates('ctime','day','DESC')
 
def datetimes(self, field_name, kind, order='ASC', tzinfo=None):
    # 根据时间进行某一部分进行去重查找并截取指定内容,将时间转换为指定时区时间
    # kind只能是 "year", "month", "day", "hour", "minute", "second"
    # order只能是:"ASC"  "DESC"
    # tzinfo时区对象
    models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.UTC)
    models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.timezone('Asia/Shanghai'))
 
    """
    pip3 install pytz
    import pytz
    pytz.all_timezones
    pytz.timezone(‘Asia/Shanghai’)
    """
 
def none(self):
    # 空QuerySet对象
 
 
####################################
# METHODS THAT DO DATABASE QUERIES #
####################################
 
def aggregate(self, *args, **kwargs):
   # 聚合函数,获取字典类型聚合结果,对整个表做聚合
   from django.db.models import Count, Avg, Max, Min, Sum
   result = models.UserInfo.objects.aggregate(k=Count('u_id', distinct=True), n=Count('nid'))
   ===> {'k': 3, 'n': 4}
result = models.UserInfo.objects.aggregate(n=count('nid'))相当于下面sql语句:
select count(nid) as n from UserInfo 
如果添加distinct=True则先去重在聚合
 
 
def count(self):
   # 获取个数
 
def get(self, *args, **kwargs):
   # 获取单个对象
 
def create(self, **kwargs):
   # 创建对象
 
def bulk_create(self, objs, batch_size=None):
    # 批量插入
    # batch_size表示一次插入的个数
    objs = [
        models.DDD(name='r11'),
        models.DDD(name='r22')
    ]
   参数10表示一次插入多少个,即将数据进行分批插入
    models.DDD.objects.bulk_create(objs, 10)
 
def get_or_create(self, defaults=None, **kwargs):
    # 如果存在,则获取,否则,创建
    # defaults 指定创建时,其他字段的值,defaults后面的内容表示前面的username不存在的时候,用于创建
    obj, created = models.UserInfo.objects.get_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 2})
 
def update_or_create(self, defaults=None, **kwargs):
    # 如果存在,则更新,否则,创建
    # defaults 指定创建时或更新时的其他字段
    obj, created = models.UserInfo.objects.update_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 1})
 
def first(self):
   # 获取第一个
 
def last(self):
   # 获取最后一个
 
def in_bulk(self, id_list=None):
   # 根据主键ID进行查找
   id_list = [11,21,31]
   models.DDD.objects.in_bulk(id_list)
 
def delete(self):
   # 删除
 
def update(self, **kwargs):
    # 更新
 
def exists(self):
   # 是否有结果

model里的验证功能(较弱)

当在models里写如下代码:

class UserInfo(models.Model):
    name = models.CharField(max_length=32)
    email = models.EmailField()

这样在views函数里用下面方式添加用户时:

models.UserInfo.objects.create(name="root",email="123")

或者:

obj = models.UserInfo(name="zhaofan",email = "123")

obj.save()

这种情况下email的格式并不对,但是这样添加时是可以添加成功,并不会报错

但是通过obj = models.UserInfo(name="zhaofan",email = "123")方式添加用户时,obj这里有一个方法full_clean(),当添加这个方法的时候就会添加验证功能,完整代码如下:

obj = models.UserInfo(name="zhaofan",email = "123")

obj.full_clean()

obj.save()

这样就会提示如下错误:

查看full_clean源码

可以看出clean_fields是对各个字段进行验证

下面还有一个clean方法,查看源码

可以看出这里是Django预留的一个钩子

对于这个clean钩子的一个使用例子:

from django.core.exceptions import  ValidationError
class UserInfo(models.Model):
    name = models.CharField(max_length=32)
    email = models.EmailField()
 
    def clean(self):
        c = UserInfo.objects.filter(name=self.name).count()
        if c:
            raise ValidationError(message="用户名已经存在",code="cc1")

这里通过clean定制了一个name值唯一的操作

这里需要知道full_clean验证的顺序:

1、    验证每个字段的正则

2、    验证clean钩子函数

原文地址:https://www.cnblogs.com/bingabcd/p/7237194.html