0
点赞
收藏
分享

微信扫一扫

Java--作用域,构造器,this

孟佳 2023-12-08 阅读 53

目录

一.多表查询

1.基于对象的跨表查询

一对多查询(publish与book)

一对一查询(Author与AuthorDetail)

多对多查询(Author与Book)

2.基于双下划线的跨表查询

一对多查询

多对多查询

一对一查询

连续跨表查询

3.聚合查询与分组查询

聚合查询

aggregate(*args,**kwargs)

分组查询

annotate()

4.F查询与Q查询

F查询:拿到某个字段在表中具体的值

Q查询:为了组装成与、或、非 条件

二.其他字段和字段参数

1.ORM字段

2.ORM字段参数

3.关系字段

三.Django与Ajax

1.什么是Ajax

2.基于jquery的Ajax实现

3.案例

(1)通过Ajax实现前端输入两个数字,服务器做加法返回到前端页面

(2)基于Ajax进行登录验证

4.文件上传

请求头ContentType

(1)application/x-www-form-urlencoded

(2)multipart/form-data

(3)application/json

基于Form表单上传文件:

视图函数:

5.基于Ajax上传文件

6.Ajax提交json格式数据

7.Django内置的serializers(把对象序列化成json字符串)


一.多表查询

1.基于对象的跨表查询

一对多查询(publish与book)

正向查询(按字段:publish)

# 查询主键为1的书籍的出版社所在的城市
book_obj=Book.objects.filter(pk=1).first()
# book_obj.publish 是主键为1的书籍对象关联的出版社对象
print(book_obj.publish.city)

反向查询(按表名:book_set)

publish=Publish.objects.get(name="苹果出版社")
#publish.book_set.all() : 与苹果出版社关联的所有书籍对象集合
book_list=publish.book_set.all()    
for book_obj in book_list:
       print(book_obj.title)
# 一对多正向查询
 book=Book.objects.filter(name='红楼梦').first()
 print(book.publish)#与这本书关联的出版社对象
 print(book.publish.name)
 # 一对多反向查询
 # 人民出版社出版过的书籍名称
 pub=Publish.objects.filter(name='人民出版社').first()
 ret=pub.book_set.all()
 print(ret)

一对一查询(Author与AuthorDetail)

正向查询(按字段:authorDetail):

justin=Author.objects.filter(name="justin").first()
print(justin.authorDetail.telephone)

反向查询(按表名:author):

# 查询所有住址在北京的作者的姓名
 
authorDetail_list=AuthorDetail.objects.filter(addr="beijing")
for obj in authorDetail_list:
     print(obj.author.name)
# 一对一正向查询
# lqz的手机号
lqz=Author.objects.filter(name='lqz').first()
tel=lqz.author_detail.telephone
print(tel)
# 一对一反向查询
# 地址在北京的作者姓名
author_detail=AuthorDatail.objects.filter(addr='北京').first()
name=author_detail.author.name
print(name)

多对多查询(Author与Book)

正向查询(按字段:authors):

# 眉所有作者的名字以及手机号
 
book_obj=Book.objects.filter(title="眉").first()
authors=book_obj.authors.all()
for author_obj in authors:
     print(author_obj.name,author_obj.authorDetail.telephone)

反向查询(按表名:book_set):

# 查询justin出过的所有书籍的名字
  author_obj=Author.objects.get(name="justin")
  book_list=author_obj.book_set.all()        #与justin作者相关的所有书籍
  for book_obj in book_list:
    print(book_obj.title)
# 正向查询----查询红楼梦所有作者名称
book=Book.objects.filter(name='红楼梦').first()
ret=book.authors.all()
print(ret)
for auth in ret:
print(auth.name)
# 反向查询 查询lqz这个作者写的所有书
author=Author.objects.filter(name='lqz').first()
ret=author.book_set.all()
print(ret)

2.基于双下划线的跨表查询

一对多查询

# 练习:  查询苹果出版社出版过的所有书籍的名字与价格(一对多)

# 正向查询 按字段:publish

queryResult=Book.objects.filter(publish__name="苹果出版社").values_list("title","price")

# 反向查询 按表名:book
queryResult=Publish.objects.filter(name="苹果出版社").values_list("book__title","book__price")
查询的本质一样,就是select from的表不一样
# 正向查询按字段,反向查询按表名小写
# 查询红楼梦这本书出版社的名字
# select * from app01_book inner join app01_publish
# on app01_book.publish_id=app01_publish.nid
ret=Book.objects.filter(name='红楼梦').values('publish__name')
print(ret)
ret=Publish.objects.filter(book__name='红楼梦').values('name')
print(ret)

多对多查询

# 练习: 查询lqz出过的所有书籍的名字(多对多)

# 正向查询 按字段:authors:
queryResult=Book.objects.filter(authors__name="lqz").values_list("title")

# 反向查询 按表名:book
queryResult=Author.objects.filter(name="lqz").values_list("book__title","book__price")
# 正向查询按字段,反向查询按表名小写
# 查询红楼梦这本书出版社的名字
# select * from app01_book inner join app01_publish
# on app01_book.publish_id=app01_publish.nid
ret=Book.objects.filter(name='红楼梦').values('publish__name')
print(ret)
ret=Publish.objects.filter(book__name='红楼梦').values('name')
print(ret)
# sql 语句就是from的表不一样
# -------多对多正向查询
# 查询红楼梦所有的作者
ret=Book.objects.filter(name='红楼梦').values('authors__name')
print(ret)
# ---多对多反向查询
ret=Author.objects.filter(book__name='红楼梦').values('name')
ret=Author.objects.filter(book__name='红楼梦').values('name','author_detail__addr')
print(ret)

一对一查询

# 查询lqz的手机号

# 正向查询
ret=Author.objects.filter(name="lqz").values("authordetail__telephone")

# 反向查询
ret=AuthorDetail.objects.filter(author__name="lqz").values("telephone")
# 查询lqz的手机号
# 正向查
ret=Author.objects.filter(name='lqz').values('author_detail__telephone')
print(ret)
# 反向查
ret= AuthorDatail.objects.filter(author__name='lqz').values('telephone')
print(ret)

连续跨表查询

# 练习: 查询人民出版社出版过的所有书籍的名字以及作者的姓名

# 正向查询
queryResult=Book.objects.filter(publish__name="人民出版社").values_list("title","authors__name")
# 反向查询
queryResult=Publish.objects.filter(name="人民出版社").values_list("book__title","book__authors__age","book__authors__name")


# 练习: 手机号以151开头的作者出版过的所有书籍名称以及出版社名称

# 方式1:
queryResult=Book.objects.filter(authors__authorDetail__telephone__regex="151").values_list("title","publish__name")
# 方式2:    
ret=Author.objects.filter(authordetail__telephone__startswith="151").values("book__title","book__publish__name")
# ----进阶练习,连续跨表
# 查询手机号以33开头的作者出版过的书籍名称以及书籍出版社名称
# author_datail author book publish
# 基于authorDatail表

ret=AuthorDatail.objects.filter(telephone__startswith='33').values('author__book__name','author__book__publish__name')
print(ret)

# 基于Author表
 ret=Author.objects.filter(author_detail__telephone__startswith=33).values('book__name','book__publish__name')
print(ret)

# 基于Book表
ret=Book.objects.filter(authors__author_detail__telephone__startswith='33').values('name','publish__name')
print(ret)

# 基于Publish表  
ret=Publish.objects.filter(book__authors__author_detail__telephone__startswith='33').values('book__name','name')
    print(ret)

3.聚合查询与分组查询

聚合查询

aggregate(*args,**kwargs)
# 计算所有图书的平均价格
from django.db.models import Avg
Book.objects.all().aggregate(Avg('price'))
#{'price__avg': 34.35}
Book.objects.aggregate(average_price=Avg('price'))
#{'average_price': 34.35}

如果你希望生成不止一个聚合,可以向aggregate()子句中添加另一个参数

# 如果你也想知道所有图书价格的最大值和最小值,可以这样查询:
from django.db.models import Avg, Max, Min
Book.objects.aggregate(Avg('price'), Max('price'), Min('price'))
#{'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}
# 查询所有书籍的平均价格
from django.db.models import Avg,Count,Max,Min
ret=Book.objects.all().aggregate(Avg('price'))
# {'price__avg': 202.896}
# 可以改名字
ret=Book.objects.all().aggregate(avg_price=Avg('price'))
# 统计平均价格和最大价格
ret=Book.objects.all().aggregate(avg_price=Avg('price'),max_price=Max('price'))
# 统计最小价格
ret = Book.objects.all().aggregate(avg_price=Avg('price'), min_price=Min('price'))
# 统计个数和平均价格
ret = Book.objects.all().aggregate(avg_price=Avg('price'), max_price=Max('price'),count=Count('price'))
ret = Book.objects.all().aggregate(avg_price=Avg('price'), max_price=Max('price'),count=Count('nid'))
print(ret)

分组查询

annotate()
# 统计每本书的作者个数
from django.db.models import Avg, Max, Sum, Min, Max, Count
book_list = models.Book.objects.all().annotate(author_num=Count("authors"))
for book in book_list:
     print(book.name)
     print(book.author_num)
book_list = models.Book.objects.all().annotate(author_num=Count("authors")).values('name','author_num')
print(book_list)




# 统计每一个出版社的最便宜的书
publishList=Publish.objects.annotate(MinPrice=Min("book__price"))
for publish_obj in publishList:
    print(publish_obj.name,publish_obj.MinPrice)




# 统计每一本以py开头的书籍的作者个数:
queryResult=Book.objects.filter(title__startswith="Py").annotate(num_authors=Count('authors'))




# 统计不止一个作者的图书(作者数量大于1):
ret=models.Book.objects.annotate(author_num=Count("authors")).filter(author_num__gt=1).values('name','author_num')
print(ret)

4.F查询与Q查询

F查询:拿到某个字段在表中具体的值

# 查询评论数大于收藏数的书籍
from django.db.models import F
Book.objects.filter(commnetNum__lt=F('keepNum'))

Django支持F()对象之间以及F()对象和常数之间的加减乘除和取模的操作

# 查询评论数大于收藏数2倍的书籍
Book.objects.filter(commnetNum__lt=F('keepNum')*2)

修改操作也可以使用F函数,比如将每一本书的价格提高30元

Book.objects.all().update(price=F("price")+30)

Q查询:为了组装成与、或、非 条件

from django.db.models import Q
Q(title__startswith='Py')

Q对象可以使用&和|操作符组合起来当一个操作符在两个Q对象上使用时会产生一个新的Q对象

bookList=Book.objects.filter(Q(authors__name="XXX")|Q(authors__name="justin"))


# 等同于:
    WHERE name ="XXX" OR name ="justin"

二.其他字段和字段参数

1.ORM字段

  • AutoField
    • int自增列,必须填入参数primary_key=True,当model中如果没有自增列,则会自动创建一个名为id的列
  • IntegerField
    • 一个整数类型,范围在-2147483648 to 2147483647
  • CharField
    • 日期字段,日期格式YYYY-MM-DD,相当于Python中的datetime.date()实例
  • DateField
    • 日期字段,日期格式YYYY-MM-DD,相当于Python中的datetime.date()实例
  • DateTimeField
    • 日期时间字段,格式YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],相当于Python中的datetime.datetime()实例
AutoField(Field)
- int自增列,必须填入参数 primary_key=True

BigAutoField(AutoField)
- bigint自增列,必须填入参数 primary_key=True

注:当model中如果没有自增列,则自动会创建一个列名为id的列
from django.db import models

class UserInfo(models.Model):
# 自动创建一个列名为id的且为自增的整数列
username = models.CharField(max_length=32)

class Group(models.Model):
# 自定义自增列
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)

SmallIntegerField(IntegerField):
- 小整数 -32768 ~ 32767

PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
- 正小整数 0 ~ 32767
IntegerField(Field)
- 整数列(有符号的) -2147483648 ~ 2147483647

PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
- 正整数 0 ~ 2147483647

BigIntegerField(IntegerField):
- 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807

BooleanField(Field)
- 布尔值类型

NullBooleanField(Field):
- 可以为空的布尔值

CharField(Field)
- 字符类型
- 必须提供max_length参数, max_length表示字符长度

TextField(Field)
- 文本类型

EmailField(CharField):
- 字符串类型,Django Admin以及ModelForm中提供验证机制

IPAddressField(Field)
- 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制

GenericIPAddressField(Field)
- 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
- 参数:
protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启此功能,需要protocol="both"

URLField(CharField)
- 字符串类型,Django Admin以及ModelForm中提供验证 URL

SlugField(CharField)
- 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)

CommaSeparatedIntegerField(CharField)
- 字符串类型,格式必须为逗号分割的数字

UUIDField(Field)
- 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证

FilePathField(Field)
- 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能
- 参数:
path,                      文件夹路径
match=None,                正则匹配
recursive=False,           递归下面的文件夹
allow_files=True,          允许文件
allow_folders=False,       允许文件夹

FileField(Field)
- 字符串,路径保存在数据库,文件上传到指定目录
- 参数:
upload_to = ""      上传文件的保存路径
storage = None      存储组件,默认django.core.files.storage.FileSystemStorage

ImageField(FileField)
- 字符串,路径保存在数据库,文件上传到指定目录
- 参数:
upload_to = ""      上传文件的保存路径
storage = None      存储组件,默认django.core.files.storage.FileSystemStorage
width_field=None,   上传图片的高度保存的数据库字段名(字符串)
height_field=None   上传图片的宽度保存的数据库字段名(字符串)

DateTimeField(DateField)
- 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]

DateField(DateTimeCheckMixin, Field)
- 日期格式      YYYY-MM-DD

TimeField(DateTimeCheckMixin, Field)
- 时间格式      HH:MM[:ss[.uuuuuu]]

DurationField(Field)
- 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型

FloatField(Field)
- 浮点型

DecimalField(Field)
- 10进制小数
- 参数:
max_digits,小数总长度
decimal_places,小数位长度

BinaryField(Field)
- 二进制类型
对应关系:
    '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)',

2.ORM字段参数

#### null

用于表示某个字段可以为空。

#### **unique**

如果设置为unique=True 则该字段在此表中必须是唯一的 。

#### **db_index**

如果db_index=True 则代表着为此字段设置索引。

#### **default**

为该字段设置默认值。

###  DateField和DateTimeField

#### auto_now_add

配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。

#### auto_now

配置上auto_now=True,每次更新数据记录的时候会更新该字段。
null                数据库中字段是否可以为空
db_column           数据库中字段的列名
db_tablespace
default             数据库中字段的默认值
primary_key         数据库中字段是否为主键
db_index            数据库中字段是否可以建立索引
unique              数据库中字段是否可以建立唯一索引
unique_for_date     数据库中字段【日期】部分是否可以建立唯一索引
unique_for_month    数据库中字段【月】部分是否可以建立唯一索引
unique_for_year     数据库中字段【年】部分是否可以建立唯一索引

verbose_name        Admin中显示的字段名称
blank               Admin中是否允许用户输入为空
editable            Admin中是否可以编辑
help_text           Admin中该字段的提示信息
choices             Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1)

error_messages      自定义错误信息(字典类型),从而定制想要显示的错误信息;
字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date
如:{'null': "不能为空.", 'invalid': '格式错误'}

validators          自定义错误验证(列表类型),从而定制想要的验证规则
from django.core.validators import RegexValidator
from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\
MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator
如:
test = models.CharField(
max_length=32,
error_messages={
'c1': '优先错信息1',
'c2': '优先错信息2',
'c3': '优先错信息3',
},
validators=[
RegexValidator(regex='root_\d+', message='错误了', code='c1'),
RegexValidator(regex='root_112233\d+', message='又错误了', code='c2'),
EmailValidator(message='又错误了', code='c3'), ]
                            )

3.关系字段

三.Django与Ajax

1.什么是Ajax

  • 同步交互:客户端发出一个请求后,等待服务器响应结束后才能发出第二个请求
  • 异步交互:客户端发出一个请求后,无需等待服务器响应结束就可以发出第二个请求

2.基于jquery的Ajax实现

<button class="send_Ajax">send_Ajax</button>
<script>

       $(".send_Ajax").click(function(){

           $.ajax({
               url:"/handle_Ajax/",
               type:"POST",
               data:{username:"Yuan",password:123},
               success:function(data){
                   console.log(data)
               },
               
               error: function (jqXHR, textStatus, err) {
                        console.log(arguments);
                    },

               complete: function (jqXHR, textStatus) {
                        console.log(textStatus);
                },

               statusCode: {
                    '403': function (jqXHR, textStatus, err) {
                          console.log(arguments);
                     },

                    '400': function (jqXHR, textStatus, err) {
                        console.log(arguments);
                    }
                }

           })

       })

</script>

3.案例

(1)通过Ajax实现前端输入两个数字,服务器做加法返回到前端页面

def test_ajax(requests):
    n1=int(requests.POST.get('n1'))
    n2=int(requests.POST.get('n2'))
    return HttpResponse(n1+n2)
$("#submit").click(function () {
    $.ajax({
        url: '/test_ajax/',
        type: 'post',
        data: {
            n1: $("#num1").val(),
            n2: $("#num2").val()
        },
        success: function (data) {
            console.log(data)
            $("#sum").val(data)
        },

    })
})
<input type="text" id="num1">+<input type="text" id="num2">=<input type="text" id="sum">
<button id="submit">计算</button>

(2)基于Ajax进行登录验证

用户在表单输入用户名和密码,通过Ajax提交给服务器,服务器验证后返回响应信息,客户端通过响应信息确定是否登录成功,成功则跳转首页,失败则在页面显示相应的报错信息

def auth(request):
    back_dic={'user':None,'message':None}
    name=request.POST.get('user')
    password=request.POST.get('password')
    print(name)
    print(password)
    user=models.user.objects.filter(name=name,password=password).first()
    print(user)
    # print(user.query)
    if user:
        back_dic['user']=user.name
        back_dic['message']='成功'
    else:
        back_dic['message']='用户名或密码错误'
    import json
    return HttpResponse(json.dumps(back_dic))
$("#submit3").click(function () {
        $.ajax({
            url: '/auth/',
            type: 'post',
            data: {
                'user': $("#id_name").val(),
                'password': $('#id_password').val()
            },

            success: function (data) {
                {#console.log(data)#}
                var data=JSON.parse(data)
                if (data.user){
                    location.href='https://www.baidu.com'
                }else {
                    $(".error").html(data.message).css({'color':'red','margin-left':'20px'})
                }
            }


        })
    }
)

traditional:true(可以序列化一层列表,多层不行,要转JSON格式上传)

4.文件上传

请求头ContentType

(1)application/x-www-form-urlencoded
(2)multipart/form-data
(3)application/json
基于Form表单上传文件:
<form action="/file_put/" method="post" enctype="multipart/form-data">
    用户名:<input type="text" name="name">
    头像:<input type="file" name="avatar" id="avatar1">
<input type="submit" value="提交">
</form>
视图函数:
def file_put(request):
    if request.method=='GET':
        return render(request,'file_put.html')
    else:
        # print(request.POST)
        # print(request.POST)
        print(request.body)  # 原始的请求体数据 
        print(request.GET)  # GET请求数据 
        print(request.POST)  # POST请求数据 
        print(request.FILES)  # 上传的文件数据
        # print(request.body.decode('utf-8'))
        print(request.body.decode('utf-8'))

        print(request.FILES)
        file_obj=request.FILES.get('avatar')
        print(type(file_obj))
        with open(file_obj.name,'wb') as f:
            for line in file_obj:
                f.write(line)
        return HttpResponse('ok')

5.基于Ajax上传文件

$("#ajax_button").click(function () {
    var formdata=new FormData()
    formdata.append('name',$("#id_name2").val())
    formdata.append('avatar',$("#avatar2")[0].files[0])
    $.ajax({
        url:'',
        type:'post',
        processData:false, //告诉jQuery不要去处理发送的数据
        contentType:false,// 告诉jQuery不要去设置Content-Type请求头
        data:formdata,
        success:function (data) {
            console.log(data)

        }

    })
})

6.Ajax提交json格式数据

$("#ajax_test").click(function () {
    var dic={'name':'lqz','age':18}
    $.ajax({
        url:'',
        type:'post',
        contentType:'application/json',  //一定要指定格式 contentType: 'application/json;charset=utf-8',
        data:JSON.stringify(dic),    //转换成json字符串格式
        success:function (data) {
            console.log(data)
        }

    })

})

7.Django内置的serializers(把对象序列化成json字符串)

from django.core import serializers
from django.core import serializers
def test(request):
    book_list = Book.objects.all()    
    ret = serializers.serialize("json", book_list)
    return HttpResponse(ret)
举报

相关推荐

0 条评论