1.简述http协议及常用请求头。
1.http协议就是超文本传输协议,是用户(客户端)与服务器(服务端)的一种请求和响应的标准格式.常用的http协议为http1.1 2.是基于tcp/ip的应用层协议 3.http的工作原理可大致分为5步: 3.1 客户端连接到服务器 3.2 客户端发送一个http请求给服务端 3.3 服务端响应一个http响应给客户端 3.4 释放连接 3.5 浏览器解析html,用户通过浏览器看到了页面 4.http特点: 4.1 短连接 4.2 无状态 5.http格式的内容: 5.1 http请求内容: 请求行:请求方法/nURL/n版本协议/r/n 请求头:头部字段:值/r/n...头部字段:值/r/n/r/n 请求数据 5.2 http响应内容: 状态行:版本协议/n状态码/n状态描述/r/n 响应头:头部字段:值/r/n...头部字段:值/r/n/r/n 响应数据 6.常用请求方法: get方法:在服务器中检索数据,展示数据时用get方法. post方法:将数据发送到服务器以创建或更新资源. 7.常用请求头和响应头: 请求头:cookie:之前服务器设置的一个http协议cookie;host:表示服务器的域名以及服务器所监听的端口号 响应头:set-cookie:设置cookie;status:通用网关接口的响应头字段,用来说明当前http连接的响应状态2.列举常见的请求方法
1.get请求方法:在服务器中搜索数据,给用户展示数据时使用,在处理数据,不能用get请求,不安全,浏览器会缓存get请求. 2.post请求方法:将数据发送到服务器用以创建或更新资源.3.举例常见的状态码
1xx消息 : 请求已被服务器接收,继续处理 2xx成功 : 请求已成功被服务器接收/理解并接受,如:200:表示服务器已成功接受请求,并将返回客户端请求的最终结果. 3xx重定向 : 需要后续操作才能完成这一请求.如:301:表示客户端所请求的网页已经永久移动到新的位置 4xx请求错误 : 请求含有词法错误或者无法被执行.如:404:表示请求失败,客户端请求的资源没有找到或者不存在 5xx服务器错误 : 服务器处理某个正确的请求发生时发生错误.如:503:表示服务器由于临时的服务器过载或者是维护,无法解决当前的请求4.django对数据查询结果排序怎么做, 降序怎么做
ret = models.T1.objects.all().order_by('price','id') #queryset类型,按照price进行升序,price相同的数据,按照id进行升序 ret = models.T1.objects.all().order_by('-price') #按price降序排列 ret = models.T1.objects.all().order_by('price').reverse()#对查询结果反向排序5.django的orm中如何查询 id 不等于5的元素
ret = models.T1.objects.exclude(id=5) #queryset类型,返回id不等于5的所有对象,也可以在queryset类型基础上执行6.使用Django中model filter条件过滤方法,把下边sql语句转化成python代码
select * from company where title like '%abc%' or mecount>999 order by createtime desc; models.Company.objects.filter(Q(title__contains='abc')|Q(mecount__gt=999)).order_by('createtime').reverse()7.从输入http://www.baidu.com/到页面返回, 中间都是发生了什么
1.浏览器向 DNS 服务器请求解析该 URL 中的域名所对应的 IP 地址; 2.解析出 IP 地址后,根据该 IP 地址和默认端口 80,和服务器建立TCP连接; 3.浏览器发出读取文件(URL 中域名后面部分对应的文件)的HTTP 请求,该请求报文作为 TCP 三次握手的第三个报文的数据发送给服务器; 4.服务器对浏览器请求作出响应,并把对应的 html 文本发送给浏览器; 5.释放 TCP连接; 6.浏览器将该 html 文本并显示内容;8.django请求的生命周期
9.简述django中间件及其应用场景
如果你想修改请求,例如被传送到view中的HttpRequest对象。或者你想修改view返回的HttpResponse对象,这些都可以通过中间件来实现。 可能你还想在view执行之前做一些操作,这种情况就可以用 middleware来实现 总之,中间件是帮助我们在视图函数执行之前和执行之后都可以做一些额外的操作,它本质上就是一个自定义类,类中定义了几个方法,Django框架会在请求的特定的时间去执行这些方法.10.简述django FBV和CBV
用函数写视图函数views.py(FBV) 1.函数的参数 函数的第一个参数是request对象: request.GET返回的是GET参数的类字典对象 request.POST返回的是POST参数的类字典对象 request.method #请求方法 request.path #请求路径 request.path_info #返回用户访问url,不包括域名 从第二个参数开始接受的是url中的参数: 有名分组:按名称接收 无名分组:按位置顺序接收 2.函数的返回值 有三种: HttpResponse:返回字符串 redirect:重定向 render:返回html页面,可以传字典渲染页面 用类写views.py(CBV) urls写法:views.类名.as_view() from django.views import View 继承View这个django自带的类 类中可以定义get/post方法,视图文件会可以将请求方法分发到同名的类方法去处理 原因:继承了dispatch方法,而dispatch方法用了反射,将请求方法分发到同名的类方法去处理 还可以拓展dispatch方法,用super().dispatch(request,*args,**kwargs)11.列举django orm 中你了解的所有方法
单表: 增: 1.通过添加属性, save() obj = models.Book( title='金瓶梅后传', price=2.8, # pub_date='2000-08-12', #这样的格式字符串 pub_date=datetime.datetime.now(), # 时间日期类型 publish='31期红浪漫出版社', ) obj.save() 2.通过create方法 obj= models.Book.objects.create( title='金瓶梅前传', price=9.9, # pub_date='2000-08-12', pub_date=datetime.datetime.now(), publish='31期夕阳红出版社', ) 3.批量添加 bulk_create obj_list = [] for i in range(1,4): obj = models.Book( title='少妇白洁' + str(i), price=i, pub_date=f'2000-08-1{i}', publish='31期夕阳红出版社', ) obj_list.append(obj) models.Book.objects.bulk_create(obj_list) 删:.delete() query类型数据和模型类对象都可以调用delete方法 改: 1 .update() 2.对象.属性修改 模型类对象不能直接使用update方法 obj = models.Book.objects.get(id=6) obj.price = 18 obj.save() 查:13种方法: all() , filter(条件) , get(条件) , exclude(条件) , order_by() , reverse(),count(),first(),last(),exists(),values(),values_list(),distinct() ret = models.T1.objects.all() #queryset类型 ret = models.T1.objects.filter(title='少妇白洁1') #queryset类型 ret = models.T1.objects.get(title='少妇白洁1') #获取有且只有一条数据,找不到/超过一条都会报错 ret = models.T1.objects.exclude(id=5) #queryset类型,返回id不等于6的所有对象,也可以在queryset类型基础上执行 ret = models.T1.objects.all().order_by('price','id') #queryset类型,按照price进行升序,price相同的数据,按照id进行升序 ret = models.T1.objects.all().order_by('-price') #按price降序排列 ret = models.T1.objects.all().order_by('price').reverse()#对查询结果反向排序 ret = models.T1.objects.all().count() #对queryset类型数据调用,返回查询到的对象数量 ret = models.T1.objects.all().first() #model对象,返回第一条记录 ret = models.T1.objects.all()[0] #同first,不支持负索引 ret = models.T1.objects.all().last() #返回最后一条记录 ret = models.T1.objects.all().exists() #QuerySet包含数据,就返回True,否则返回False ret = models.T1.objects.values('title','price') #querset类型,<QuerySet [{'title': '少妇白洁1', 'price': Decimal('1.00')}... ret = models.T1.objects.all().values('title','price') #还可以通过queryset类型数据来调用 ret = models.T1.objects.all().values_list('title','price')#用法同values,返回的是元组 filter基于双下划线的模糊查询 __year , __day , __startswith , __istartswith , __endswith , __icontains , __in , __range , __gt , __gte , __lt , __lte 多表: 创建: # 与AuthorDetail建立一对一的关系,一对一的这个关系字段写在两个表的任意一个表里面都可以 ad = models.OneToOneField(to="AuthorDetail", to_field='id', on_delete=models.CASCADE) publish=models.ForeignKey(to="Publish") #默认级联删除,默认关联的是另外一张表的id字段 authors=models.ManyToManyField(to='Author',) #自动创建第三张表,id author_id book_id,不会作为本表的字段出现 增: 一对多 关联的类.对象/字段 models.Book.objects.create( title='金瓶梅第二部', publishDate='2018-08-08', price=22, # publishs=models.Publish.objects.get(id=1), publishs_id=1, ) 多对多 add obj = models.Book.objects.filter(id=1).first() a1 = models.Author.objects.get(id=1) a2 = models.Author.objects.get(id=2) obj.authors.add(a1,a2) obj.authors.add(1,2) obj.authors.add(*[1,2]) 删除: 一对一和一对多 ,基本和单表一样(级联删除) .delete() 多对多删除 clear remove ret = models.Book.objects.get(id=2) ret.authors.clear() # 清空该书籍对应的第三张表中的记录 ret.authors.remove(3,4) #指定删除该书和哪些作者的关系 改: 一对一/一对多修改 update 多对多修改 set方法 查: 基于双下划线的跨表查询 表名__字段 聚合查询 计算Avg,Max,Min,Count,Sum aggregate 分组查询 ---> group by annotate F查询 --->for 循环 针对本表不同字段数据进行对比时或者本表字典做一些统一修改时使用F查询 # 点赞数大于评论数的 ret = models.Book.objects.filter(dianzan__gt=F('comment')) # 所有书籍上调10块 models.Book.objects.all().update(price=F('price')+10) Q查询 # | -- or # & -- and # ~ -- not 事务: 1.装饰器:@transaction.atomic 2.with语句:with transaction.atomic() 锁: create、update、delete操作时,mysql自动加行级互斥锁,select_for_update()12.django中的F的作用
F查询 --->for 循环 针对本表不同字段数据进行对比时或者本表字典做一些统一修改时使用F查询 如: # 点赞数大于评论数的 ret = models.Book.objects.filter(dianzan__gt=F('comment')) # 所有书籍上调10块 models.Book.objects.all().update(price=F('price')+10)13.django中的Q的作用
当我们在查询的条件中需要组合条件时(例如两个条件“且”或者“或”)时。我们可以使用Q()查询对象。 如: # | -- or # & -- and # ~ -- not14.django中如何执行原生SQL
#方式一: from django.db import connection cursor = connection.cursor() cursor.execute('select * from app01_book;') print(cursor.fetchall()) #方式二: import pymysql conn = pymysql.connect(host='', user="", password="", database="") cursor = conn.cursor() sql = 'select * from app01_usermsg where username = %s and pwd = %s' res = cursor.execute(sql, (uname,pwd)) cursor.close() conn.close() #方式三: ret = models.Author.objects.raw('select * from app01_author;') #只限于本表操作 print(ret) for i in ret: print(i.name)15.django中filter和exclude的区别
filter:是查询出符合设定条件的查询集 exclude:是查询出不符合设定条件的查询集16.django中values和values_list的区别
values:返回的是querset类型,里面是键值对 values_list:用法同values但是返回的是元组17.如何使用django orm批量创建数据
#批量添加 bulk_create obj_list = [] for i in range(1,4): obj = models.Book( title='少妇白洁' + str(i), price=i, pub_date=f'2000-08-1{i}', publish='31期夕阳红出版社', ) obj_list.append(obj) models.Book.objects.bulk_create(obj_list)18.django的Model中的ForeignKey字段中的on_delete参数有什么作用
on_delete:当该表中的某条数据删除后,关联外键的操作 on_delete的参数设置: 1.on_delete=models.CASCADE-->级联删除 2.PROTECT: 保护模式,如果采用该选项,删除的时候,会抛出ProtectedError错误 3.SET_NULL: 置空模式,删除的时候,外键字段被设置为空,前提就是blank=True, null=True,定义该字段的时候,允许为空。 4.SET_DEFAULT: 设置默认值,删除的时候,外键字段设置为默认值,所以定义外键的时候注意加上一个默认值。 5.SET(): 自定义一个值,该值当然只能是对应的实体19.django中csrf的实现机制
csrf : 跨站请求攻击,比如,一个客户端发送请求通过浏览器访问了A服务器, 浏览器会将客户端的cookie值储存在本地, 当用户再通过浏览器去访问B服务器时,B服务器中后台如果向A服务器发送一个请求, 也可以通过浏览器的认证,可以对用户在A网站的数据进行修改. 总之,就是B网站通过A网站的漏洞,在用户不知情的情况下,通过向A网站发送请求,更改用户数据,实现跨站攻击. csrf认证 : 解决csrf攻击的最直接的办法就是 生成一个随机的csrftoken值,保存在用户的页面上, 每次请求都带着这个值过来完成校验, django会验证表单中的token和cookie中token 是否能解出同样的secret,secret一样则本次请求合法 .20.基于django使用ajax发送post请求时,有哪种方法携带csrf token
//需要从cookie中拿取token添加到请求头中 //方式一: $.ajax({ url: "/cookie_ajax/", type: "POST", data: { "username": "chao", "password": 123456, "csrfmiddlewaretoken": $("[name = 'csrfmiddlewaretoken']").val() // 使用jQuery取出csrfmiddlewaretoken的值,拼接到data中 }, success: function (data) { console.log(data); } }) //方式二: $.ajaxSetup({ data: {csrfmiddlewaretoken: '{{ csrf_token }}' }, });21.django路由系统中name的作用
给url匹配模式起别名,这样别的地方使用到这个路径时,可以用别名来反向解析.如果路径变化,整个项目不受影响. {% url 'home' %}-->在html文件中反向解析 from django.urls import reverse reverse("index") #在视图文件中反向解析 如果有两个应用下的路径别名相同时,反向解析时,得到的结果都是settings文件中最后一个应用的路径,这时就需要分配命名空间来保证反向解析路径的正确.22.使用orm和原生sql的优缺点
SQL: # 优点: 执行速度快 # 缺点: 编写复杂,开发效率不高 ---------------------------------------------------- ORM: # 优点: 让用户不再写SQL语句,提高开发效率 可以很方便地引入数据缓存之类的附加功能 # 缺点: 在处理多表联查、where条件复杂查询时,ORM的语法会变得复杂。 没有原生SQL速度快23.简述MVC和MTV
提及mvc和mtv,有必要先简单的说下设计模式和框架模式. 设计模式:解决某一些特殊问题的一种思想和思路; 框架模式:解决如何设计程序框架,在框架模式中会包含多种设计模式,与设计模式是一种包含关系 mvc和mtv是目前流行的两种框架模式:django就是一种mtv框架 mvc: Models 模型层,在程序中用于处理数据逻辑的部分,(主要是处理数据),主要负责在数据库中对数据的存取操作,其实就是对数据库的增删改查的操作; Views 视图层 ,在应用程序中处理显示部分的内容(html,jsp); Controllers 控制层 ,处理用户交互的部分,主要作用于M和V之间做协调,通常是负责从模型层中抽取数据,再进行业务处理,最后将数据传给视图层,并将视图传给客户端. mtv: M 代表模型(Model):负责业务对象和数据库的关系映射(ORM); T 代表模板 (Template):负责如何把页面展示给用户(html); V 代表视图(View):负责业务逻辑,并在适当时候调用Model和Template; 还需要一个URL分发器,它的作用是将一个个URL的页面请求分发给不同的View处理,View再调用相应的Model和Template24.Django 创建项目的命令
django-admin startproject mysite #创建了一个名为"mysite"的Django 项目 python manage.py startapp blog #创建应用 python manage.py runserver 8000 #启动django项目25.Django 创建项目后,项目文件夹下的组成部分
manage.py ----- Django项目里面的工具,通过它可以调用django shell和数据库,启动关闭项目与项目交互等,不管你将框架分了几个文件,必然有一个启动文件,其实他们本身就是一个文件。 settings.py ---- 包含了项目的默认设置,包括数据库信息,调试标志以及其他一些工作的变量。 urls.py ----- 负责把URL模式映射到应用程序。 wsgi.py ---- runserver命令就使用wsgiref模块做简单的web server,后面会看到renserver命令,所有与socket相关的内容都在这个文件里面了,目前不需要关注它。26.Django中models利用ORM对Mysql进行查表的语句
单表: 13种方法: all() , filter(条件) , get(条件) , exclude(条件) , order_by() , reverse(),count(),first(),last(),exists(),values(),values_list(),distinct() ret = models.T1.objects.all() #queryset类型 ret = models.T1.objects.filter(title='少妇白洁1') #queryset类型 ret = models.T1.objects.get(title='少妇白洁1') #获取有且只有一条数据,找不到/超过一条都会报错 ret = models.T1.objects.exclude(id=5) #queryset类型,返回id不等于6的所有对象,也可以在queryset类型基础上执行 ret = models.T1.objects.all().order_by('price','id') #queryset类型,按照price进行升序,price相同的数据,按照id进行升序 ret = models.T1.objects.all().order_by('-price') #按price降序排列 ret = models.T1.objects.all().order_by('price').reverse()#对查询结果反向排序 ret = models.T1.objects.all().count() #对queryset类型数据调用,返回查询到的对象数量 ret = models.T1.objects.all().first() #model对象,返回第一条记录 ret = models.T1.objects.all()[0] #同first,不支持负索引 ret = models.T1.objects.all().last() #返回最后一条记录 ret = models.T1.objects.all().exists() #QuerySet包含数据,就返回True,否则返回False ret = models.T1.objects.values('title','price') #querset类型,<QuerySet [{'title': '少妇白洁1', 'price': Decimal('1.00')}... ret = models.T1.objects.all().values('title','price') #还可以通过queryset类型数据来调用 ret = models.T1.objects.all().values_list('title','price')#用法同values,返回的是元组 filter基于双下划线的模糊查询 __year , __day , __startswith , __istartswith , __endswith , __icontains , __in , __range , __gt , __gte , __lt , __lte 多表: 基于双下划线的跨表查询 表名__字段 聚合查询 计算Avg,Max,Min,Count,Sum aggregate 分组查询 ---> group by annotate F查询 --->for 循环 针对本表不同字段数据进行对比时或者本表字典做一些统一修改时使用F查询 # 点赞数大于评论数的 ret = models.Book.objects.filter(dianzan__gt=F('comment')) # 所有书籍上调10块 models.Book.objects.all().update(price=F('price')+10) Q查询 # | -- or # & -- and # ~ -- not27.模型类关系如何建立
# 与AuthorDetail建立一对一的关系,一对一的这个关系字段写在两个表的任意一个表里面都可以 ad = models.OneToOneField(to="AuthorDetail", to_field='id', on_delete=models.CASCADE) # publish=models.ForeignKey(to="Publish",to_field="id",on_delete=models.CASCADE) publish=models.ForeignKey(to="Publish") #默认级联删除,默认关联的是另外一张表的id字段 authors=models.ManyToManyField(to='Author',) #自动创建第三张表,id author_id book_id,不会作为本表的字段出现28.django如何自定义中间件
1 在应用下创建一个文件夹 2 在文件夹中创建一个py文件 3 在py文件中继承MiddlewareMixin 4 在settings.py文件中做如下配置 from django.utils.deprecation import MiddlewareMixin class Auth(MiddlewareMixin): #类名随意,继承MiddlewareMixin # 如果想对请求做一些统一处理,那么就定义process_request方法 def process_request(self,request): print('请求来啦!!!快看!!!!') def process_response(self,request,response): # response 视图响应回来的响应对象 # response.status_code = 201 print('请求走啦!!!') return response 中间件可以定义五个方法,分别是:(主要的是process_request和process_response) process_request(self,request) 执行顺序:按setting文件配置的顺序从上到下依次执行. 如果return了一个httpresponse对象则会在这个方法中断你的请求,直接返回给用户,不会走视图函数 process_view(self, request, view_func, view_args, view_kwargs) 它应该返回None或一个HttpResponse对象。 如果返回None,Django将继续处理这个请求,执行任何其他中间件的process_view方法,然后在执行相应的视图。 如果它返回一个HttpResponse对象,Django不会调用对应的视图函数。它将执行中间件的process_response方法并将应用到该HttpResponse并返回结果。 process_template_response(self,request,response) process_template_response是在视图函数执行完成后立即执行, 但是它有一个前提条件,那就是视图函数返回的对象有一个render()方法 process_exception(self, request, exception) 处理视图函数的异常顺序是倒序 这个方法只有在视图函数中出现异常了才执行,它返回的值可以是一个None也可以是一个HttpResponse对象 如果是HttpResponse对象,Django将调用模板和中间件中的process_response方法,并返回给浏览器,否则将默认处理异常 如果返回一个None,则交给下一个中间件的process_exception方法来处理异常。它的执行顺序也是按照中间件注册顺序的倒序执行。 process_response(self, request, response) 执行顺序:在视图函数之后执行,按setting文件配置的倒叙从下到上依次执行.29.什么 csrf 攻击原理?如何解决
解决csrf攻击的最直接的办法就是生成一个随机的csrftoken值,保存在用户的页面上,每次请求都带着这个值过来完成校验,django会验证表单中的token和cookie中token是否能解出同样的secret,secret一样则本次请求合法.30.启动 Django 服务的方法
python manage.py runserver 8000 #启动django项目31.对 cookie 与 session 的了解?他们能单独用吗
cookie: 产生原因: http协议(基于tcp)的特点:1 无连接(短连接);2 无状态. http协议不会记录客户端和服务端的任何信息,导致服务端和客户端不能维持会话 正是由于http无状态的特性,所以出现了cookie(一种浏览器技术).请求头健值对. 工作原理: 浏览器访问服务端,带着一个空的cookie,然后由服务器产生内容,浏览器收到相应后保存在本地; 当浏览器再次访问时,浏览器会自动带上Cookie,这样服务器就能通过Cookie的内容来判断这个是“谁”了。 cookie操作: request.COOKIES['key'] #获取cookie rep = render(request, ...) rep.set_cookie(key,value,...) #设置cookie ret.set_cookie('username', 'xxx') #改,相同的键设置不同的值就是修改 ret.delete_cookie('username') #删 session: 产生原因: 1.cookie是明文存储的 2.大小限制: Cookie大小上限为4KB; 一个服务器最多在客户端浏览器上保存20个Cookie; 一个浏览器最多保存300个Cookie,因为一个浏览器可以访问多个服务器。 特点: cookie中放的数据是密文的 数据存在服务端,没有大小上限 一个浏览器对应一个服务端,就是一个session 工作原理: 如下图. 操作session: #设置session request.session['k1'] = 123 # request.session #1 生成一个随机字符串 #2 将随机字符串放到cookie中,名称为sessionid #3 将设置的session数据,序列化+加密,保存到了django-session表中 request.session.setdefault('k1',123) #获取session request.session['k1'] # request.session['is_login'] # 1 取出请求中cookie键为sessionid的值 # 2 通过这个值到django-session表中获取数据 # 3 将数据解密并且反序列化得到原来的数据 request.session.get('k1',None) #删除session del request.session['k1'] #清空session request.session.flush() # 注销 def logout(requset): requset.session.flush() # 1 删除cookie中的数据 # 2 删除数据库中django-session表中的记录 return redirect('/login/')32.Django 里 QuerySet 的 get 和 filter 方法的区别
输入参数: get的参数只能是model中定义的那些字段,只支持严格匹配 filter的参数可以是字段,也可以是扩展的where查询关键字,如in,like等 返回值: get返回值是一个定义的model对象 filter返回值是一个新的QuerySet对象,然后可以对QuerySet在进行查询返回新的QuerySet对象,支持链式操作。QuerySet一个集合对象,可使用迭代或者遍历,切片等,但是不等于list类型 异常: get只有一条记录返回的时候才正常,也就说明get的查询字段必须是主键或者唯一约束的字段。当返回多条记录或者是没有找到记录的时候都会抛出异常。 filter有没有匹配记录都可以。33.生成迁移文件和执行迁移文件的命令是什么
python manage.py makemigrations #生成迁移文件 python manage.py migrate #执行迁移文件34.HttpRequest 和 HttpResponse 是什么,干嘛用的
HttpRequest: django 接受用户发送多来的请求报文后,将报文封装到 HttpRequest 对象中去. 视图的第一个参数必须是 HttpRequest 对象. request.GET返回的是GET参数的类字典对象 request.POST返回的是POST参数的类字典对象 request.method #请求方法 request.path #请求路径 request.path_info #返回用户访问url,不包括域名 HttpResponse: 返回的是一个应答的数据报文。render 内部已经封装好了 HttpResponse 类 HttpResponse:返回字符串 redirect:重定向 render:返回html页面,可以传字典渲染页面35.url有名分组和无名分组参数都是什么意思
urls: 写路径时正则匹配: 有名分组:给分组命名,以关键字参数传过去 无名分组:分组时候没有名字,是以位置参数传入的 视图函数: 从第二个参数开始接受的是url中的参数: 有名分组:按名称接收 无名分组:按位置顺序接收36.url命名空间是干什么用的
有多个应用时,通常django项目下的urls文件会用include方法进行路径分发. 当不同的应用中路径的别名相同时,在进行url别名反向解析时,得到的结果都是settings文件中最后一个应用的路径. 解决办法:在include中加上namespace='app01'即为:include('app01.urls' namespace='app01')--->把app01下的所有路径划分了一个单独的空间. 这样即使app中URL的命名相同,也可以反向解析出正确的URL.37.写一个简单ajax发送post请求的代码
ajax用法:异步请求 局部刷新 <body> {# <form action=""> #} 用户名: <input type="text" id="uname"> 密码: <input type="password" id="pwd"> <input type="button" value="确定" id="btn"> <span id="error_msg" style="color:red;font-size: 12px;"></span> {#</form>#} </body> <script src="{% static 'js/jquery.js' %}"></script> <script> $('#btn').click(function () { var uname = $('#uname').val(); var pwd = $('#pwd').val(); $.ajax({ url:'/login/', type:'post', data:{username:uname,password:pwd}, // request .POST.get('username') success:function (res) { // res接收的是请求成功之后的响应结果, // 这对响应结果做一些事情 console.log(res, typeof res); if (res === 'ok'){ location.href = '/xx/'; }else { $('#error_msg').text('用户名或者密码有误'); } }, error:function (res) { //res 请求失败之后获取到的响应结果 5xx,4xx console.log('>>>>>>',res); if (res.status === 403){ $('#error_msg').text(res.responseText); } //else if (res.status === 500){ //} } }) }) </script> def login(request): if request.method == 'GET': print('看登录页面') return render(request, 'login.html') uname = request.POST.get('username') if uname == 'chao': # <QueryDict: {'username': ['root'], 'password': ['123']}> # return render(request,'xx.html') return HttpResponse('ok') else: ret = HttpResponse('用户名不对') # 200 # ret.status_code = 403 return ret