Q查询进阶操作

from django.db.models import Q
q_obj = Q()   # 1.产生q对象
q_obj.connector = 'or'  # 默认多个条件的连接是and可以修改为or
q_obj.children.append(('pk', 1))  # 2.添加查询条件
q_obj.children.append(('price__gt', 2000)) # 支持添加多个
res = models.Book.objects.filter(q_obj)  #查询支持直接填写q对象
print(res)

ORM查询优化

1.ORM的查询默认都是惰性查询
2.ORM的查询自带分页处理
3.only与defer
	'''数据对象+含有指定字段对应的数据'''
res = models.Book.objects.only('title','price')
print(res)   # queryset [数据对象、数据对象]
for obj in res:
   # print(obj.title) # 点击括号内填写的字段   不走SQL查询
    # print(obj.price)
    print(obj.publish_time)  # 可以点击括号内没有的字段获取数据 但是会走SQL查询

res = models.Book.objects.defer('title','price')
# print(res)   #  [数据对象,数据对象,]
for obj in res:
    # print(obj.title)
    # print(obj.price)
    print(obj.publish_time)
"""
only可以将括号里列举的字段封装到数据对象里面,当用对象点括号里面的字段时,只会执行一条SQL查询,但是如果点括号里面没有的字段,每拿到一条数据就执行一次SQL语句。

defer也可以将括号里列举的字段封装到数据对象里面,当用对象点括号里面的字段时,每拿到一条数据就执行一次SQL语句,如果点括号里面没有的字段,则只执行一条SQL查询
"""
4.select_related(连表查询、不支持多对多字段)与prefetch_related(子查询)
# res = models.Book.objects.all()
# for obj in res:
#     print(obj.publish.name)  # 每次查询都需要走SQL
# res = models.Book.objects.select_related('publish')  # 先连表后查询封装
# res1 = models.Author.objects.select_related('author_detail')  # 括号内不支持多对多字段 其他两个都可以
# print(res1)
# for obj in res:
#     print(obj.publish.name)  # 不再走SQL查询
# print(res)
res = models.Book.objects.prefetch_related('publish') # 子查询
for obj in res:
    print(obj.publish.name)

ORM事务操作

"""
1.事务的四大特性(ACID)
    原子性、一致性、隔离性、持久性
2.相关SQL关键字
     start transaction;
     rollback;
     commit;
     savepoint;
3.相关重要概念
     脏读、幻读、不可重复读、MVCC多版本控制。。。。
"""
django orm 提供了至少三种开启事务的方式
    方式1:配置文件数据库相关添加键值对       全局有效
      "ATOMIC_REQUESTS":True每次请求所涉及到的orm操作同属于一个事务
    方式2:装饰器                          局部有效
    from django.db import transaction 
    @transaction.atomic
    def index():pass 
    方式3:with上下文管理                    局部有效
    from django.db import transaction
    def reg():
        with transaction.atomic():
        pass

ORM常用字段类型

AutoField
    parimary_key=True
Charfield
    max_length
IntegerField
BigIntergerField
DecimalField
    max_digits  decimal_places
DateField
    auto_now  auto_now_add
DateTimeField
     auto_now  auto_now_add
BooleanField
     传布尔值自动存0或1
TextField
     存储大段文本
EmailField
     存储邮箱格式数据
FileField
     传文件对象 自动保持到提前配置好的路径下并存储该路径信息
ORM还支持用户自定义字段类型
    class MyCharField(models.Field):
        def __init__(self,max_length,*args,**kwargs):
            self.max_length = max_length
            super().__init__(max_length=max_length,*args,**kwargs)
        def db_type(self,connection):
            return 'char(%s)' % self.max_length
        
class User(models.Model):
    name = models.CharField(max_length=32)
    info = MyCharField(max_length=64)

ORM常用字段参数

primary_key        主键值
verbose_name       注释
max_length         字段长度
max_digits         数字总共多少位
decimal_places     小数点后面的位数
auto_now           每次操作数据自动更新时间
auto_now_add       首次创建自动更新时间后续不自动更新
null               允许字段为空
default            字段默认值(一般为1)
unique             唯一值
db_index           给字段添加索引
choices            当某个字段的可能性能够被列举完全的情况下使用 
   性别、学历、工作状态、 。。。
   class User(models.Model):
        name = models.CharField(max_length=32)
        info = MyCharField(max_length=64)
        # 提前列举好对应关系
    gender_choice = ((1, '男性'), (2, '女性'), (3, '其他'),)
    gender = models.IntegerField(choices=gender_choice, null=True)

添加好表数据在console内执行
# from app01 import models
# user_obj = models.User.objects.filter(pk=1).first()
# user_obj.gender
# user_obj.get_gender_display()

to                   关联表
to_field             关联字段(不写默认关联数据主键)
on_delete            当删除关联表中的数据时,当前表与其关联的级联的行为
    1、models.CASCADE
       级联操作,当主表中被连接的一条数据删除时,从表中所有与之关联的数据同时被删除
    2、models.SET_NULL
       当主表中的一行数据删除时,从表中所有与之关联的数据的相关字段设置为null,此时注意定义外键时,这个字段必须可以允许为空
    3、models.PROTECT
      当主表中的一行数据删除时,由于从表中相关字段是受保护的外键,所以都不允许删除
    4、models.SET_DEFAULT
       当主表中的一行数据删除时,从表中所有相关的数据的关联字段设置为默认值,此时注意定义外键时,这个外键字段应该有一个默认值
    5、models.SET()
        当主表中中的一条数据删除时,从表中所有的关联数据字段设置为SET()中设置的值,与models.SET_DEFAULT相似,只不过此时从表中的相关字段不需要设置default参数
    6、models.DO_NOTHING
        什么都不做,一切都看数据库级别的约束,主数据库级别的默认约束为RESTRICT,这个约束与django中的models.PROTECT相似

Ajax

异步提交  局部刷新
ajax不是一门新的技术并且有很多版本 我们目前学习的jQuery版本(版本无所谓 本质一样就可以)

基本语法
<script>
// 1.先获取两个框里面的数据

        {#console(v1Val,v2Val)#}
    //2.给按钮绑定点击事件
    $('#subBtn').click(function () {
        let v1Val = $('#d1').val();
        let v2Val = $('#d2').val();
        //3.发送ajax请求
        $.ajax({
                url: '',//后端地址  三种填写方式 与form标签的action一致
                type: 'post',//请求方式  默认也是get
                data: {'v1': v1Val, 'v2': v2Val}, //发送的数据
                success: function (args) {// 后端返回结果之后自动触发 args接收后端返回的数据
                    $('#d3').val(args)
                }
            }
        )
    })
</script>
def ab_ajax_func(request):
    if request.method == 'POST':
        print(request.POST)
        v1 =request.POST.get('v1')
        v2 = request.POST.get('v2')
        res = int(v1) + int(v2)
        return HttpResponse(res)
        # return HttpResponse('ajax好哟用用')
    return render(request,'abAjax.html')
            
在此基础需要定义三个input框 绑定d1/d2/d3

Content-Type

1.urlencoded
    ajax默认的编码格式、form表单默认也是
    数据格式  xxx=yyy&uuu=ooo&aaa=kkk
    django后端会自动处理到request.POST中
    
2.formdata
    django后端针对普通的键值对还是处理到request.POST中但是针对文件会处理到request.FILES中
    
3.application/json
    form表单不支持  ajax可以
    <script>
    $('#d1').click(function () {
        $.ajax({
            url:'',
            type:'post',
            data:JSON.stringify({'name':'jason','age':18}),  // 千万不要骗人家
            contentType:'application/json',
            success:function (args) {
                alert(args)
            }

        })
    })
</script>
  后端需要从request.body中获取并自己处理

ajax携带文件数据

<script>
   $('#d3').click(function(){
       //1.先产生一个FormData对象
       let myFormDataObj = new FormData();
       //2.往该对象中添加文件数据
       myFormDataObj.append('name','jason');
       myFormDataObj.append('age',18);
       //3.往该对象中添加文件数据
       myFormDataObj.append('file',$('#d2')[0].files[0])
       // 4.发送ajax请求
       $.ajax({
           url:'',
           type:'post',
           data:myFormDataObj,
           // ajax发送文件固定的两个配置
           contenType:false,
           processData:false,
           success:function(args){
               alert(args)
           }
       })
   })

ORM字段与MySQL字段对应关系

对应关系:
    'AutoField': 'integer AUTO_INCREMENT',
    'BigAutoField': 'bigint AUTO_INCREMENT',
    'BinaryField': 'longblob',
    'BooleanField': 'bool',
    'CharField': 'varchar(%(max_length)s)',
    'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
    'DateField': 'date',
    'DateTimeField': 'datetime',
    'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
    'DurationField': 'bigint',
    'FileField': 'varchar(%(max_length)s)',
    'FilePathField': 'varchar(%(max_length)s)',
    'FloatField': 'double precision',
    'IntegerField': 'integer',
    'BigIntegerField': 'bigint',
    'IPAddressField': 'char(15)',
    'GenericIPAddressField': 'char(39)',
    'NullBooleanField': 'bool',
    'OneToOneField': 'integer',
    'PositiveIntegerField': 'integer UNSIGNED',
    'PositiveSmallIntegerField': 'smallint UNSIGNED',
    'SlugField': 'varchar(%(max_length)s)',
    'SmallIntegerField': 'smallint',
    'TextField': 'longtext',
    'TimeField': 'time',
    'UUIDField': 'char(32)',

ORM字段与MySQL字段对应关系

如果你想知道你对数据库进行操作时,Django内部到底是怎么执行它的sql语句时可以加下面的配置来查看

在Django项目的settings.py文件中,在最后复制粘贴如下代码

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}

补充:

除了配置外,还可以通过一点.query即可查看查询语句,具体操作如下:
image