文章目录

  • 第四章:Django特级篇
    • 聚合查询
    • 分组查询
    • F与Q查询
    • django中如何开启事务
    • orm中常用字段及参数
    • 数据库查询优化
    • 图书管理的图书增删改查
    • choices参数(数据库字段设计常见)
    • MTV与MVC模型
    • 多对多三种创建方式
    • Ajax
    • 小例子
    • 前后端传输数据的编码格式(contentType)
    • ajax发送json格式数据
    • ajax发送文件;
    • django自带的序列化组件(drf做铺垫)
    • ajax结合layer弹窗实现二次确认
    • 批量插入
    • 分页器

第四章:Django特级篇

聚合查询

# 聚合查询      aggregate"""聚合查询通常情况下都是配合分组一起使用的只要是跟数据库相关的模块 基本上都在django.db.models里面如果上述没有那么应该在django.db里面"""from app01 import modelsfrom django.db.models import Max,Min,Sum,Count,Avg# 1 所有书的平均价格# res = models.Book.objects.aggregate(Avg('price'))# print(res)# 2.上述方法一次性使用res = models.Book.objects.aggregate(Max('price'),Min('price'),Sum('price'),Count('pk'),Avg('price'))print(res)

分组查询

# 分组查询  annotate"""MySQL分组查询都有哪些特点分组之后默认只能获取到分组的依据 组内其他字段都无法直接获取了严格模式ONLY_FULL_GROUP_BY"""from django.db.models import Max, Min, Sum, Count, Avg# 1.统计每一本书的作者个数# res = models.Book.objects.annotate()  # models后面点什么 就是按什么分组# res = models.Book.objects.annotate(author_num=Count('authors')).values('title','author_num')"""author_num是我们自己定义的字段 用来存储统计出来的每本书对应的作者个数"""# res1 = models.Book.objects.annotate(author_num=Count('authors__id')).values('title','author_num')# print(res,res1)"""代码没有补全 不要怕 正常写补全给你是pycharm给你的 到后面在服务器上直接书写代码 什么补全都没有 颜色提示也没有"""# 2.统计每个出版社卖的最便宜的书的价格(作业:复习原生SQL语句 写出来)# res = models.Publish.objects.annotate(min_price=Min('book__price')).values('name','min_price')# print(res)# 3.统计不止一个作者的图书# 1.先按照图书分组 求每一本书对应的作者个数# 2.过滤出不止一个作者的图书# res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1).values('title','author_num')# """# 只要你的orm语句得出的结果还是一个queryset对象# 那么它就可以继续无限制的点queryset对象封装的方法## """# print(res)# 4.查询每个作者出的书的总价格# res = models.Author.objects.annotate(sum_price=Sum('book__price')).values('name','sum_price')# print(res)"""如果我想按照指定的字段分组该如何处理呢?models.Book.objects.values('price').annotate()后续BBS作业会使用你们的机器上如果出现分组查询报错的情况你需要修改数据库严格模式"""

F与Q查询

# F查询# 1.查询卖出数大于库存数的书籍# F查询"""能够帮助你直接获取到表中某个字段对应的数据"""from django.db.models import F# res = models.Book.objects.filter(maichu__gt=F('kucun'))# print(res)# 2.将所有书籍的价格提升500块# models.Book.objects.update(price=F('price') + 500)# 3.将所有书的名称后面加上爆款两个字"""在操作字符类型的数据的时候 F不能够直接做到字符串的拼接"""from django.db.models.functions import Concatfrom django.db.models import Valuemodels.Book.objects.update(title=Concat(F('title'), Value('爆款')))# models.Book.objects.update(title=F('title') + '爆款')  # 所有的名称会全部变成空白
 # Q查询# 1.查询卖出数大于100或者价格小于600的书籍# res = models.Book.objects.filter(maichu__gt=100,price__lt=600)"""filter括号内多个参数是and关系"""from django.db.models import Q# res = models.Book.objects.filter(Q(maichu__gt=100),Q(price__lt=600))  # Q包裹逗号分割 还是and关系# res = models.Book.objects.filter(Q(maichu__gt=100)|Q(price__lt=600))  # | or关系# res = models.Book.objects.filter(~Q(maichu__gt=100)|Q(price__lt=600))  # ~ not关系# print(res)  # <QuerySet []># Q的高阶用法  能够将查询条件的左边也变成字符串的形式q = Q()q.connector = 'or'q.children.append(('maichu__gt',100))q.children.append(('price__lt',600))res = models.Book.objects.filter(q)  # 默认还是and关系print(res)

django中如何开启事务

"""
事务ACID原子性不可分割的最小单位一致性跟原子性是相辅相成隔离性事务之间互相不干扰持久性事务一旦确认永久生效事务的回滚 rollback事务的确认commit
"""
# 目前你只需要掌握Django中如何简单的开启事务
# 事务from django.db import transactiontry:with transaction.atomic():# sql1# sql2...# 在with代码快内书写的所有orm操作都是属于同一个事务except Exception as e:print(e)print('执行其他操作')

orm中常用字段及参数

# 更多字段
直接参考博客:https://www.cnblogs.com/Dominic-Ji/p/9203990.htmlAutoField主键字段 primary_key=TrueCharField                varcharverbose_name 字段的注释max_length     长度IntegerField          int
BigIntegerField     bigintDecimalFieldmax_digits=8decimal_places=2EmailFiled              varchar(254)DateField                   date
DateTimeField           datetimeauto_now:每次修改数据的时候都会自动更新当前时间auto_now_add:只在创建数据的时候记录创建时间后续不会自动修改了BooleanField(Field)                - 布尔值类型该字段传布尔值(False/True)  数据库里面存0/1TextField(Field)                   - 文本类型该字段可以用来存大段内容(文章、博客...)  没有字数限制后面的bbs作业 文章字段用的就是TextFieldFileField(Field)                  - 字符类型upload_to = "/data"给该字段传一个文件对象,会自动将文件保存到/data目录下然后将文件路径保存到数据库中/data/a.txt后面bbs作业也会涉及# 更多字段
直接参考博客:https://www.cnblogs.com/Dominic-Ji/p/9203990.html# django除了给你提供了很多字段类型之外 还支持你自定义字段
class MyCharField(models.Field):def __init__(self,max_length,*args,**kwargs):self.max_length = max_length# 调用父类的init方法super().__init__(max_length=max_length,*args,**kwargs)  # 一定要是关键字的形式传入def db_type(self, connection):"""返回真正的数据类型及各种约束条件:param connection::return:"""return 'char(%s)'%self.max_length# 自定义字段使用
myfield = MyCharField(max_length=16,null=True)# 外键字段及参数
unique=TrueForeignKey(unique=True)   ===           OneToOneField()# 你在用前面字段创建一对一 orm会有一个提示信息 orm推荐你使用后者但是前者也能用db_index如果db_index=True 则代表着为此字段设置索引(复习索引是什么)to_field设置要关联的表的字段  默认不写关联的就是另外一张的主键字段on_delete当删除关联表中的数据时,当前表与其关联的行的行为。"""django2.X及以上版本 需要你自己指定外键字段的级联更新级联删除"""

数据库查询优化

only与defer
select_related与prefetch_related"""
orm语句的特点:惰性查询如果你仅仅只是书写了orm语句 在后面根本没有用到该语句所查询出来的参数那么orm会自动识别 直接不执行
"""
# only与defer
# res = models.Book.objects.all()# print(res)  # 要用数据了才会走数据库# 想要获取书籍表中所有数的名字# res = models.Book.objects.values('title')# for d in res:#     print(d.get('title'))# 你给我实现获取到的是一个数据对象 然后点title就能够拿到书名 并且没有其他字段# res = models.Book.objects.only('title')# res = models.Book.objects.all()# print(res)  # <QuerySet [<Book: 三国演义爆款>, <Book: 红楼梦爆款>, <Book: 论语爆款>, <Book: 聊斋爆款>, <Book: 老子爆款>]># for i in res:# print(i.title)  # 点击only括号内的字段 不会走数据库# print(i.price)  # 点击only括号内没有的字段 会重新走数据库查询而all不需要走了res = models.Book.objects.defer('title')  # 对象除了没有title属性之外其他的都有for i in res:print(i.price)"""defer与only刚好相反defer括号内放的字段不在查询出来的对象里面 查询该字段需要重新走数据而如果查询的是非括号内的字段 则不需要走数据库了"""# select_related与prefetch_related
# select_related与prefetch_related  跟跨表操作有关# res = models.Book.objects.all()# for i in res:#     print(i.publish.name)  # 每循环一次就要走一次数据库查询# res = models.Book.objects.select_related('publish')  # INNER JOIN"""select_related内部直接先将book与publish连起来 然后一次性将大表里面的所有数据全部封装给查询出来的对象这个时候对象无论是点击book表的数据还是publish的数据都无需再走数据库查询了select_related括号内只能放外键字段    一对多 一对一多对多也不行"""# for i in res:#     print(i.publish.name)  # 每循环一次就要走一次数据库查询res = models.Book.objects.prefetch_related('publish')  # 子查询"""prefetch_related该方法内部其实就是子查询将子查询查询出来的所有结果也给你封装到对象中给你的感觉好像也是一次性搞定的"""for i in res:print(i.publish.name)

图书管理的图书增删改查

from django.shortcuts import render,redirect,HttpResponse
from app01 import models
# Create your views here.def home(request):return render(request,'home.html')def book_list(request):# 先查询出所有的书籍信息 传递给html页面book_queryset = models.Book.objects.all()return render(request,'book_list.html',locals())def book_add(request):if request.method == 'POST':# 获取前端提交过来的所有数据title = request.POST.get("title")price = request.POST.get("price")publish_date = request.POST.get("publish_date")publish_id = request.POST.get("publish")authors_list = request.POST.getlist("authors")  # [1,2,3,4,]# 操作数据库存储数据# 书籍表book_obj = models.Book.objects.create(title=title,price=price,publish_date=publish_date,publish_id=publish_id)# 书籍与作者的关系表book_obj.authors.add(*authors_list)# 跳转到书籍的展示页面"""redirect括号内可以直接写url其实也可以直接写别名但是如果你的别名需要额外给参数的话,那么就必须使用reverse解析了"""return redirect('book_list')# 先获取当前系统中所有的出版社信息和作者信息publish_queryset = models.Publish.objects.all()author_queryset = models.Author.objects.all()return render(request,'book_add.html',locals())def book_edit(request,edit_id):# 获取当前用户想要编辑的书籍对象 展示给用户看edit_obj = models.Book.objects.filter(pk=edit_id).first()if request.method == 'POST':title = request.POST.get("title")price = request.POST.get("price")publish_date = request.POST.get("publish_date")publish_id = request.POST.get("publish")authors_list = request.POST.getlist("authors")  # [1,2,3,4,]models.Book.objects.filter(pk=edit_id).update(title=title,price=price,publish_date=publish_date,publish_id=publish_id)# 该第三张关系表edit_obj.authors.set(authors_list)return redirect('book_list')publish_queryset = models.Publish.objects.all()author_queryset = models.Author.objects.all()return render(request,'book_edit.html',locals())def book_delete(request,delete_id):# 简单粗暴 直接删除models.Book.objects.filter(pk=delete_id).delete()# 直接跳转到展示页return redirect('book_list')

choices参数(数据库字段设计常见)

"""
用户表 性别学历工作经验是否结婚是否生子客户来源...
针对某个可以列举完全的可能性字段,我们应该如何存储只要某个字段的可能性是可以列举完全的,那么一般情况下都会采用choices参数
"""
class User(models.Model):username = models.CharField(max_length=32)age = models.IntegerField()# 性别gender_choices = ((1,'男'),(2,'女'),(3,'其他'),)gender = models.IntegerField(choices=gender_choices)score_choices = (('A','优秀'),('B','良好'),('C','及格'),('D','不合格'),)# 保证字段类型跟列举出来的元祖第一个数据类型一致即可score = models.CharField(choices=score_choices,null=True)"""该gender字段存的还是数字 但是如果存的数字在上面元祖列举的范围之内那么可以非常轻松的获取到数字对应的真正的内容1.gender字段存的数字不在上述元祖列举的范围内容2.如果在 如何获取对应的中文信息"""from app01 import models# models.User.objects.create(username='jason',age=18,gender=1)# models.User.objects.create(username='egon',age=85,gender=2)# models.User.objects.create(username='tank',age=40,gender=3)# 存的时候 没有列举出来的数字也能存(范围还是按照字段类型决定)# models.User.objects.create(username='tony',age=45,gender=4)# 取# user_obj = models.User.objects.filter(pk=1).first()# print(user_obj.gender)# 只要是choices参数的字段 如果你想要获取对应信息 固定写法 get_字段名_display()# print(user_obj.get_gender_display())user_obj = models.User.objects.filter(pk=4).first()# 如果没有对应关系 那么字段是什么还是展示什么print(user_obj.get_gender_display())  # 4参考博客地址:https://www.cnblogs.com/Dominic-Ji/p/10580579.html# 实际项目案例
# CRM相关内部表
class School(models.Model):"""校区表如:北京沙河校区上海校区"""title = models.CharField(verbose_name='校区名称', max_length=32)def __str__(self):return self.titleclass Course(models.Model):"""课程表如:Linux基础Linux架构师Python自动化开发精英班Python自动化开发架构师班Python基础班go基础班"""name = models.CharField(verbose_name='课程名称', max_length=32)def __str__(self):return self.nameclass Department(models.Model):"""部门表市场部     1000销售       1001"""title = models.CharField(verbose_name='部门名称', max_length=16)code = models.IntegerField(verbose_name='部门编号', unique=True, null=False)def __str__(self):return self.titleclass UserInfo(models.Model):"""员工表"""name = models.CharField(verbose_name='员工姓名', max_length=16)email = models.EmailField(verbose_name='邮箱', max_length=64)depart = models.ForeignKey(verbose_name='部门', to="Department",to_field="code")user=models.OneToOneField("User",default=1)def __str__(self):return self.nameclass ClassList(models.Model):"""班级表如:Python全栈  面授班  5期  10000  2017-11-11  2018-5-11"""school = models.ForeignKey(verbose_name='校区', to='School')course = models.ForeignKey(verbose_name='课程名称', to='Course')semester = models.IntegerField(verbose_name="班级(期)")price = models.IntegerField(verbose_name="学费")start_date = models.DateField(verbose_name="开班日期")graduate_date = models.DateField(verbose_name="结业日期", null=True, blank=True)memo = models.CharField(verbose_name='说明', max_length=256, blank=True, null=True, )teachers = models.ManyToManyField(verbose_name='任课老师', to='UserInfo',limit_choices_to={'depart':1002})tutor = models.ForeignKey(verbose_name='班主任', to='UserInfo',related_name="class_list",limit_choices_to={'depart':1006})def __str__(self):return "{0}({1}期)".format(self.course.name, self.semester)class Customer(models.Model):"""客户表"""qq = models.CharField(verbose_name='qq', max_length=64, unique=True, help_text='QQ号必须唯一')name = models.CharField(verbose_name='学生姓名', max_length=16)gender_choices = ((1, '男'), (2, '女'))gender = models.SmallIntegerField(verbose_name='性别', choices=gender_choices)education_choices = ((1, '重点大学'),(2, '普通本科'),(3, '独立院校'),(4, '民办本科'),(5, '大专'),(6, '民办专科'),(7, '高中'),(8, '其他'))education = models.IntegerField(verbose_name='学历', choices=education_choices, blank=True, null=True, )graduation_school = models.CharField(verbose_name='毕业学校', max_length=64, blank=True, null=True)major = models.CharField(verbose_name='所学专业', max_length=64, blank=True, null=True)experience_choices = [(1, '在校生'),(2, '应届毕业'),(3, '半年以内'),(4, '半年至一年'),(5, '一年至三年'),(6, '三年至五年'),(7, '五年以上'),]experience = models.IntegerField(verbose_name='工作经验', blank=True, null=True, choices=experience_choices)work_status_choices = [(1, '在职'),(2, '无业')]work_status = models.IntegerField(verbose_name="职业状态", choices=work_status_choices, default=1, blank=True,null=True)company = models.CharField(verbose_name="目前就职公司", max_length=64, blank=True, null=True)salary = models.CharField(verbose_name="当前薪资", max_length=64, blank=True, null=True)source_choices = [(1, "qq群"),(2, "内部转介绍"),(3, "官方网站"),(4, "百度推广"),(5, "360推广"),(6, "搜狗推广"),(7, "腾讯课堂"),(8, "广点通"),(9, "高校宣讲"),(10, "渠道代理"),(11, "51cto"),(12, "智汇推"),(13, "网盟"),(14, "DSP"),(15, "SEO"),(16, "其它"),]source = models.SmallIntegerField('客户来源', choices=source_choices, default=1)referral_from = models.ForeignKey('self',blank=True,null=True,verbose_name="转介绍自学员",help_text="若此客户是转介绍自内部学员,请在此处选择内部学员姓名",related_name="internal_referral")course = models.ManyToManyField(verbose_name="咨询课程", to="Course")status_choices = [(1, "已报名"),(2, "未报名")]status = models.IntegerField(verbose_name="状态",choices=status_choices,default=2,help_text=u"选择客户此时的状态")consultant = models.ForeignKey(verbose_name="课程顾问", to='UserInfo', related_name='consultanter',limit_choices_to={'depart':1001})date = models.DateField(verbose_name="咨询日期", auto_now_add=True)recv_date = models.DateField(verbose_name="当前课程顾问的接单日期", null=True)last_consult_date = models.DateField(verbose_name="最后跟进日期", )def __str__(self):return self.nameclass ConsultRecord(models.Model):"""客户跟进记录"""customer = models.ForeignKey(verbose_name="所咨询客户", to='Customer')consultant = models.ForeignKey(verbose_name="跟踪人", to='UserInfo',limit_choices_to={'depart':1001})date = models.DateField(verbose_name="跟进日期", auto_now_add=True)note = models.TextField(verbose_name="跟进内容...")def __str__(self):return self.customer.name + ":" + self.consultant.nameclass Student(models.Model):"""学生表(已报名)"""customer = models.OneToOneField(verbose_name='客户信息', to='Customer')class_list = models.ManyToManyField(verbose_name="已报班级", to='ClassList', blank=True)emergency_contract = models.CharField(max_length=32, blank=True, null=True, verbose_name='紧急联系人')company = models.CharField(verbose_name='公司', max_length=128, blank=True, null=True)location = models.CharField(max_length=64, verbose_name='所在区域', blank=True, null=True)position = models.CharField(verbose_name='岗位', max_length=64, blank=True, null=True)salary = models.IntegerField(verbose_name='薪资', blank=True, null=True)welfare = models.CharField(verbose_name='福利', max_length=256, blank=True, null=True)date = models.DateField(verbose_name='入职时间', help_text='格式yyyy-mm-dd', blank=True, null=True)memo = models.CharField(verbose_name='备注', max_length=256, blank=True, null=True)def __str__(self):return self.customer.nameclass ClassStudyRecord(models.Model):"""上课记录表 (班级记录)"""class_obj = models.ForeignKey(verbose_name="班级", to="ClassList")day_num = models.IntegerField(verbose_name="节次", help_text=u"此处填写第几节课或第几天课程...,必须为数字")teacher = models.ForeignKey(verbose_name="讲师", to='UserInfo',limit_choices_to={'depart':1002})date = models.DateField(verbose_name="上课日期", auto_now_add=True)course_title = models.CharField(verbose_name='本节课程标题', max_length=64, blank=True, null=True)course_memo = models.TextField(verbose_name='本节课程内容概要', blank=True, null=True)has_homework = models.BooleanField(default=True, verbose_name="本节有作业")homework_title = models.CharField(verbose_name='本节作业标题', max_length=64, blank=True, null=True)homework_memo = models.TextField(verbose_name='作业描述', max_length=500, blank=True, null=True)exam = models.TextField(verbose_name='踩分点', max_length=300, blank=True, null=True)def __str__(self):return "{0} day{1}".format(self.class_obj, self.day_num)class StudentStudyRecord(models.Model):'''学生学习记录'''classstudyrecord = models.ForeignKey(verbose_name="第几天课程", to="ClassStudyRecord")student = models.ForeignKey(verbose_name="学员", to='Student')record_choices = (('checked', "已签到"),('vacate', "请假"),('late', "迟到"),('noshow', "缺勤"),('leave_early', "早退"),)record = models.CharField("上课纪录", choices=record_choices, default="checked", max_length=64)score_choices = ((100, 'A+'),(90, 'A'),(85, 'B+'),(80, 'B'),(70, 'B-'),(60, 'C+'),(50, 'C'),(40, 'C-'),(0, ' D'),(-1, 'N/A'),(-100, 'COPY'),(-1000, 'FAIL'),)score = models.IntegerField("本节成绩", choices=score_choices, default=-1)homework_note = models.CharField(verbose_name='作业评语', max_length=255, blank=True, null=True)note = models.CharField(verbose_name="备注", max_length=255, blank=True, null=True)homework = models.FileField(verbose_name='作业文件', blank=True, null=True, default=None)stu_memo = models.TextField(verbose_name='学员备注', blank=True, null=True)date = models.DateTimeField(verbose_name='提交作业日期', auto_now_add=True)def __str__(self):return "{0}-{1}".format(self.classstudyrecord, self.student)"""
chocies参数使用场景是非常广泛的
"""

MTV与MVC模型

# MTV:Django号称是MTV模型
M:models
T:templates
V:views
# MVC:其实django本质也是MVC
M:models
V:views
C:controller
l:logic# vue框架:MVVM模型

多对多三种创建方式

# 全自动:利用orm自动帮我们创建第三张关系表class Book(models.Model):name = models.CharField(max_length=32)authors = models.ManyToManyField(to='Author')class Author(models.Model):name = models.CharField(max_length=32)"""优点:代码不需要你写 非常的方便 还支持orm提供操作第三张关系表的方法...不足之处:第三张关系表的扩展性极差(没有办法额外添加字段...)"""
# 纯手动class Book(models.Model):name = models.CharField(max_length=32)class Author(models.Model):name = models.CharField(max_length=32)class Book2Author(models.Model):book_id = models.ForeignKey(to='Book')author_id = models.ForeignKey(to='Author')c'''优点:第三张表完全取决于你自己进行额外的扩展不足之处:需要写的代码较多,不能够再使用orm提供的简单的方法不建议你用该方式'''# 半自动
class Book(models.Model):name = models.CharField(max_length=32)authors = models.ManyToManyField(to='Author',through='Book2Author',through_fields=('book','author'))
class Author(models.Model):name = models.CharField(max_length=32)# books = models.ManyToManyField(to='Book',#                                  through='Book2Author',#                                  through_fields=('author','book')#                                  )
class Book2Author(models.Model):book = models.ForeignKey(to='Book')author = models.ForeignKey(to='Author')"""
through_fields字段先后顺序判断的本质:通过第三张表查询对应的表 需要用到哪个字段就把哪个字段放前面你也可以简化判断当前表是谁 就把对应的关联字段放前面半自动:可以使用orm的正反向查询 但是没法使用add,set,remove,clear这四个方法
"""# 总结:你需要掌握的是全自动和半自动 为了扩展性更高 一般我们都会采用半自动(写代码要给自己留一条后路)

Ajax

"""
异步提交
局部刷新
例子:github注册动态获取用户名实时的跟后端确认并实时展示的前端(局部刷新)朝后端发送请求的方式1.浏览器地址栏直接输入url回车                        GET请求2.a标签href属性                                             GET请求3.form表单                                                        GET请求/POST请求4.ajax                                                             GET请求/POST请求    AJAX 不是新的编程语言,而是一种使用现有标准的新方法(比较装饰器)AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。(这一特点给用户的感受是在不知不觉中完成请求和响应过程)Ajax我们只学习jQuery封装之后的版本(不学原生的 原生的复杂并且在实际项目中也一般不用)
所以我们在前端页面使用ajax的时候需要确保导入了jQuery
ps:并不只有jQuery能够实现ajax,其他的框架也可以 但是换汤不换药 原理是一样的
"""

小例子

"""
页面上有三个input框在前两个框中输入数字 点击按钮 朝后端发送ajax请求后端计算出结果 再返回给前端动态展示的到第三个input框中(整个过程页面不准有刷新,也不能在前端计算)
"""
$('#btn').click(function () {// 朝后端发送ajax请求$.ajax({// 1.指定朝哪个后端发送ajax请求url:'', // 不写就是朝当前地址提交// 2.请求方式type:'post',  // 不指定默认就是get 都是小写// 3.数据{#data:{'username':'jason','password':123},#}data:{'i1':$('#d1').val(),'i2':$('#d2').val()},// 4.回调函数:当后端给你返回结果的时候会自动触发 args接受后端的返回结果success:function (args) {{#alert(args)  // 通过DOM操作动态渲染到第三个input里面#}{#$('#d3').val(args)#}console.log(typeof args)}})})"""
针对后端如果是用HttpResponse返回的数据 回调函数不会自动帮你反序列化
如果后端直接用的是JsonResponse返回的数据 回调函数会自动帮你反序列化HttpResponse解决方式1.自己在前端利用JSON.parse()2.在ajax里面配置一个参数(后面再讲)
"""

前后端传输数据的编码格式(contentType)

# 我们主要研究post请求数据的编码格式
"""
get请求数据就是直接放在url后面的
url?username=jason&password=123
"""# 可以朝后端发送post请求的方式"""1.form表单2.ajax请求""""""
前后端传输数据的编码格式urlencodedformdatajson
"""
# 研究form表单默认的数据编码格式是urlencoded数据格式:username=jason&password=123django后端针对符合urlencoded编码格式的数据都会自动帮你解析封装到request.POST中username=jason&password=123  >>> request.POST如果你把编码格式改成formdata,那么针对普通的键值对还是解析到request.POST中而将文件解析到request.FILES中form表单是没有办法发送json格式数据的# 研究ajax默认的编码格式也是urlencoded数据格式:username=jason&age=20django后端针对符合urlencoded编码格式的数据都会自动帮你解析封装到request.POST中username=jason&age=20   >>> request.POST

ajax发送json格式数据

"""
前后端传输数据的时候一定要确保编码格式跟数据真正的格式是一致的
不要骗人家!!!{"username":"jason","age":25}  在request.POST里面肯定找不到django针对json格式的数据 不会做任何的处理 request对象方法补充request.is_ajax()判断当前请求是否是ajax请求 返回布尔值"""<script>$('#d1').click(function () {$.ajax({url:'',type:'post',data:JSON.stringify({'username':'jason','age':25}),contentType:'application/json',  // 指定编码格式success:function () {}})})
</script>json_bytes = request.bodyjson_str = json_bytes.decode('utf-8')json_dict = json.loads(json_str)# json.loads括号内如果传入了一个二进制格式的数据那么内部自动解码再反序列化json_dict = json.loads(json_bytes)"""
ajax发送json格式数据需要注意点1.contentType参数指定成:application/json2.数据是真正的json格式数据3.django后端不会帮你处理json格式数据需要你自己去request.body获取并处理
"""

ajax发送文件;

"""
ajax发送文件需要借助于js内置对象FormData"""
<script>// 点击按钮朝后端发送普通键值对和文件数据$('#d4').on('click',function () {// 1 需要先利用FormData内置对象let formDateObj = new FormData();// 2 添加普通的键值对formDateObj.append('username',$('#d1').val());formDateObj.append('password',$('#d2').val());// 3 添加文件对象formDateObj.append('myfile',$('#d3')[0].files[0])// 4 将对象基于ajax发送给后端$.ajax({url:'',type:'post',data:formDateObj,  // 直接将对象放在data后面即可// ajax发送文件必须要指定的两个参数contentType:false,  // 不需使用任何编码 django后端能够自动识别formdata对象processData:false,  // 告诉你的浏览器不要对你的数据进行任何处理success:function (args) {}})})
</script>def ab_file(request):if request.is_ajax():if request.method == 'POST':print(request.POST)print(request.FILES)return render(request,'ab_file.html')"""
总结:1.需要利用内置对象FormData// 2 添加普通的键值对formDateObj.append('username',$('#d1').val());formDateObj.append('password',$('#d2').val());// 3 添加文件对象formDateObj.append('myfile',$('#d3')[0].files[0])2.需要指定两个关键性的参数contentType:false,  // 不需使用任何编码 django后端能够自动识别formdata对象processData:false,  // 告诉你的浏览器不要对你的数据进行任何处理3.django后端能够直接识别到formdata对象并且能够将内部的普通键值自动解析并封装到request.POST中 文件数据自动解析并封装到request.FILES中
"""

django自带的序列化组件(drf做铺垫)

"""
如果发现你可以直接使用MySQL但是无法使用sqlite3
不要慌张不要恐惧 你只需要按照之前MySQL的操作将sqlite3的驱动装一下即可
"""
# 需求:在前端给我获取到后端用户表里面所有的数据 并且要是列表套字典
import json
from django.http import JsonResponse
from django.core import serializers
def ab_ser(request):user_queryset = models.User.objects.all()# [{},{},{},{},{}]# user_list = []# for user_obj in user_queryset:#     tmp = {#         'pk':user_obj.pk,#         'username':user_obj.username,#         'age':user_obj.age,#         'gender':user_obj.get_gender_display()#     }#     user_list.append(tmp)# return JsonResponse(user_list,safe=False)# return render(request,'ab_ser.html',locals())# 序列化res = serializers.serialize('json',user_queryset)"""会自动帮你将数据变成json格式的字符串 并且内部非常的全面"""return HttpResponse(res)
"""
[{"pk": 1, "username": "jason", "age": 25, "gender": "male"}, {"pk": 2, "username": "egon", "age": 31, "gender": "female"},{"pk": 3, "username": "kevin", "age": 32, "gender": "others"}, {"pk": 4, "username": "tank", "age": 40, "gender": 4}]
前后端分离的项目作为后端开发的你只需要写代码将数据处理好能够序列化返回给前端即可 再写一个接口文档 告诉前端每个字段代表的意思即可[
{   "model": "app01.user", "pk": 1, "fields": {"username": "jason", "age": 25, "gender": 1}}, {   "model": "app01.user", "pk": 2, "fields": {"username": "egon", "age": 31, "gender": 2}}, {   "model": "app01.user", "pk": 3, "fields": {"username": "kevin", "age": 32, "gender": 3}},{   "model": "app01.user", "pk": 4, "fields": {"username": "tank", "age": 40, "gender": 4}}
]
写接口就是利用序列化组件渲染数据然后写一个接口文档 该交代交代一下就完事
"""

ajax结合layer弹窗实现二次确认

"""
自己要学会如何拷贝
学会基于别人的基础之上做修改
研究各个参数表示的意思 然后找葫芦画瓢
"""
<script>$('.del').click(function (){//询问框let currentBtn = $(this);var index;layer.confirm('你确定要删除吗?', {btn: ['确定','取消'] //按钮}, function(){// 发送ajax请求$.ajax({url:'/delete_user/?del_id=' + $(this).attr('del_id'),{#url:'/delete_user/' ,#}type:"get",data:{'del_id':currentBtn.attr('del_id')},beforeSend:function () {//加载层index = layer.load(0, {shade: false}); //0代表加载的风格,支持0-2},complete: function(){layer.close(index)},success:function (ret) {if (ret.code == 200) {layer.msg(ret.msg, {icon: 1}, function () {{#window.location.reload()#}currentBtn.parent().parent().remove()});} else  {layer.msg('完了,未知错误', {icon: 2});}}})});})</script>

批量插入

def ab_pl(request):# 先给Book插入一万条数据# for i in range(10000):#     models.Book.objects.create(title='第%s本书'%i)# # 再将所有的数据查询并展示到前端页面book_queryset = models.Book.objects.all()# 批量插入# book_list = []# for i in range(100000):#     book_obj = models.Book(title='第%s本书'%i)#     book_list.append(book_obj)# models.Book.objects.bulk_create(book_list)"""当你想要批量插入数据的时候 使用orm给你提供的bulk_create能够大大的减少操作时间:param request: :return: """return render(request,'ab_pl.html',locals())

分页器

"""
总数据100 每页展示10 需要10
总数据101 每页展示10 需要11
总数据99 每页展示10  需要10如何通过代码动态的计算出到底需要多少页?在制作页码个数的时候 一般情况下都是奇数个      符合中国人对称美的标准
"""
# 分页book_list = models.Book.objects.all()# 想访问哪一页current_page = request.GET.get('page',1)  # 如果获取不到当前页码 就展示第一页# 数据类型转换try:current_page = int(current_page)except Exception:current_page = 1# 每页展示多少条per_page_num = 10# 起始位置start_page = (current_page - 1) * per_page_num# 终止位置end_page = current_page * per_page_num# 计算出到底需要多少页all_count = book_list.count()page_count, more = divmod(all_count, per_page_num)if more:page_count += 1page_html = ''xxx = current_pageif current_page < 6:current_page = 6for i in range(current_page-5,current_page+6):if xxx == i:page_html += '<li class="active"><a href="?page=%s">%s</a></li>'%(i,i)else:page_html += '<li><a href="?page=%s">%s</a></li>'%(i,i)book_queryset =  book_list[start_page:end_page]"""
django中有自带的分页器模块 但是书写起来很麻烦并且功能太简单
所以我们自己想法和设法的写自定义分页器上述推导代码你无需掌握 只需要知道内部逻辑即可我们基于上述的思路 已经封装好了我们自己的自定义分页器
之后需要使用直接拷贝即可
"""

作者:吴常文
出处:https://blog.csdn.net/qq_41405475
本文版权归作者和CSDN共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

第四章:Django特级篇相关推荐

  1. oracle延时盲注如何防止,【原创】WEB安全第四章SQL注入篇21 oracle 延时注入

    WEB安全第四章SQL注入篇21 oracle 延时注入 1.简介 DBMS_LOCK.SLEEP()函数可以让一个过程休眠很多秒,但使用该函数存在许多限制.首先,不能直接将该函数注入子查询中,因为O ...

  2. 【面试宝典】软件测试工程师2021烫手精华版(第四章web测试篇)

    第四章 Web 测试 描述用浏览器访问 www.baidu.com的过程? 先要解析出 baidu.com 对应的ip 地址: • 要先使用 arp 获取默认网关的 mac 地址 • 组织数据发送给默 ...

  3. 第46章 Django完结篇,系统上线

    系统上线,在项目节点当中,占有举足轻重的地位.成了,获得的不只是荣誉的鲜花,成功的微笑,还有雷鸣般的掌声:败了,获得的不只是紧缩的眉头,苦涩的泪水,还有徘徊的脚步. 为了少走弯路,提高成功率,认真做好 ...

  4. 第四十四章 Django ORM

    1. 路由系统   def test():    pass   url(r'^test$', test)      创建app:    python3 mange.py startapp app名称 ...

  5. 第一章:Django入门篇

    文章目录 第一章:Django入门篇 一. web应用 二.HTTP协议(重要) 请求协议 响应协议 响应状态码 URL简介 三.django简介 3.2 目录介绍 3.3 启动项目 3.4 简单示例 ...

  6. 走向.NET架构设计—第四章—业务层分层架构(后篇)

    走向.NET架构设计-第四章-业务层分层架构(后篇) 前言: 在上一篇文章中,我们讨论了组织业务逻辑的模式:Transaction Script和Active Record,Domain Model. ...

  7. 【.NET Core项目实战-统一认证平台】第四章 网关篇-数据库存储配置(2)

    [.NET Core项目实战-统一认证平台]第四章 网关篇-数据库存储配置(2) 原文:[.NET Core项目实战-统一认证平台]第四章 网关篇-数据库存储配置(2) [.NET Core项目实战- ...

  8. 鸟哥的Linux私房菜(基础篇)- 第二十四章、 X Window 配置介绍

    第二十四章. X Window 配置介绍 最近升级日期:2009/08/07 在 Linux 上头的图形介面我们称之为 X Window System,简称为 X 或 X11 罗!为何称之为系统呢?这 ...

  9. 鸟哥的Linux私房菜(基础篇)-第四章、安装 CentOS 5.x 与多重开机小技巧

    第四章.安装 CentOS 5.x 与多重开机小技巧 最近更新日期:2009/08/11 Linux distributions越作越成熟,所以在安装方面也越来越简单!虽然安装非常的简单,但是刚刚前一 ...

  10. 走向.NET架构设计—第四章—业务层分层架构(前篇)

    走向.NET架构设计-第四章-业务层分层架构(前篇) 前言:在任何一个项目中业务层毫无疑问是最重要的层,所以在设计的过程中,如何组织业务层是至关重要的.本章的讨论将会涉及Flower的架构模式一书中的 ...

最新文章

  1. JavaScript 事件冒泡简介及应用(转)
  2. FreeBSD 6.0架设管理与应用-第三章 UNIX 系统入门
  3. 查看python 3.x 关键字 (保留字)(预留字)
  4. oracle ora01732,一天一小步_2008.5.02: ora-01732错误
  5. SpringCloud和SprigBoot之间的依赖关系怎么看
  6. 交叉表组件(改造 适用多个子标题)
  7. 基于平面 marker 的 Bundle Adjustmet
  8. [转]Linux下Nagios的安装与配置
  9. 用python写MapReduce函数——以WordCount为例
  10. .NET程序员面试题总结
  11. laravel对象转数组
  12. red hat linux系统下载安装
  13. MDESIGN-设计标准化系统
  14. 我的她 —— 记我的 IBM R51
  15. Android Tombstone/Crash的log分析和定位(墓碑文件)
  16. 未明学院:大学四年应当如何度过,才算不辜负?
  17. linux 6 dns,RHEL6下搭建DNS服务器
  18. 趣味测试类微信小程序
  19. 【产品】UI设计:哪些字体可以商用
  20. python ——时间间隔

热门文章

  1. ECShop 替换手机版购物首页(2)
  2. 记录安装tensorflow-gpu,版本选择问题,短平快解决战斗
  3. gitee仓库迁移至gitlab仓库简单方法,保留提交记录
  4. UnboundLocalError local variable torch referenced before assignment
  5. 2007舜宇杯ACM程序设计浙江省赛结果
  6. js内公切线切点的计算
  7. LeetCode #780 - Reaching Points
  8. 如何成为一个牛逼的程序员?
  9. 写一函数,将一个3*3的整型矩阵转置。
  10. 你知道strong和b;i和em的区别吗?