day78 面试
1 谈谈你对HTTP协议的认识。1.1 长连接
HTTP是一个属于应用层的面向对象的协议
HTTP协议工作于客户端-服务端架构为上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。Web服务器根据接收到的请求后,向客户端发送响应信息。
- 基于TCP/IP
双方建立通信的顺序,以及Web页面显示需要 处理的步骤,等等。像这样把与互联网相关联的协议集合起来总称为 TCP/IP。而http协议是基于TCP/IP协议之上的应用层协议。
- 基于请求-响应模式
HTTP协议规定,请求从客户端发出,最后服务器端响应该请求并 返回
1. 客户端连接到Web服务器
一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接。例如,http://www.luffycity.com。
2. 发送HTTP请求
通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和请求数据4部分组成。
3. 服务器接受请求并返回HTTP响应
Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。
4. 释放连接TCP连接
若connection 模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求;
5. 客户端浏览器解析HTML内容
- 无状态保存
HTTP是一种不保存状态,即无状态(stateless)协议。HTTP协议自身不对请求和响应之间的通信状态进行保存。也就是说在HTTP这个级别,协议对于发送过的请求或响应都不做持久化处理。
使用HTTP协议,每当有新的请求发送时,就会有对应的新响应产生。协议本身并不保留之前一切的请求或响应报文的信息。这是为了更快地处理大量事务,确保协议的可伸缩性,而特意把HTTP协议设计成 如此简单的。可是,随着Web的不断发展,因无状态而导致业务处理变得棘手 的情况增多了。比如,用户登录到一家购物网站,即使他跳转到该站的 其他页面后,也需要能继续保持登录状态。针对这个实例,网站为了能 够掌握是谁送出的请求,需要保存用户的状态。HTTP/1.1虽然是无状态协议,但为了实现期望的保持状态功能, 于是引入了Cookie技术。有了Cookie再用HTTP协议通信,就可以管 理状态了。
2 http 状态码
-
1xx消息——请求已被服务器接收,继续处理
-
2xx成功——请求已成功被服务器接收、理解、并接受
-
3xx重定向——需要后续操作才能完成这一请求
-
4xx请求错误——请求含有词法错误或者无法被执行
-
5xx服务器错误——服务器在处理某个正确请求时发生错误
使用HttpResponseRedirect redirect和reverse 状态码:302 临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI,
301- 资源(网页等)被永久转移到其它URL
401 Unauthorized 请求未经授权 404 Not Found 403 forbiden 405("Method Not Allowd")
503 Server Unavailable:服务器当前不能处理客户端的请求
3 http请求头
响应头
start_response('200 OK', [('Content-Type', 'text/html')])
start_response('200 OK', [('Content-Type', 'text/html'), ('k1', 'v1')])
请求头部由关键字/值对组成,每行一对,关键字和值用英文冒号“:”分隔。请求头部通知服务器有关于客户端请求的信息,典型的请求头有:(header):contype:json/
-
User-Agent:产生请求的浏览器类型。
-
Accept:客户端可识别的内容类型列表。
-
Host:请求的主机名,允许多个域名同处一个IP地址,即虚拟主机。
![img](file:///C:\Users\Administrator\AppData\Roaming\Tencent\Users\1916910438\TIM\WinTemp\RichOle\FJH6YT4M%W`U%U_{2LJLGER.png)
4 简述MVC模式和MVT模式
所谓MVC就是把Web应用分为模型(M),控制器(C)和视图(V)三层,他们之间以一种插件式的、松耦合的方式连接在一起,模型负责业务对象与数据库的映射(ORM),视图负责与用户的交互(页面),控制器接受用户的输入调用模型和视图完成用户的请求
MTV
Django的MTV模式本质上和MVC是一样的,也是为了各组件间保持松耦合关系,只是定义上有些许不同,Django的MTV分别是值:
- M 代表模型(Model): 负责业务对象和数据库的关系映射(ORM)。
- T 代表模板 (Template):负责如何把页面展示给用户(html)。
- V 代表视图(View): 负责业务逻辑,并在适当时候调用Model和Template。
除了以上三层之外,还需要一个URL分发器,它的作用是将一个个URL的页面请求分发给不同的View处理,View再调用相应的Model和Template,MTV的响应模式如下所示:
一般是用户通过浏览器向我们的服务器发起一个请求(request),这个请求回去访问视图函数,(如果不涉及到数据调用,那么这个时候视图函数返回一个模板也就是一个网页给用户),视图函数调用模型,模型去数据库查找数据,然后逐级返回,视图函数把返回的数据填充到模板中空格中,最后返回网页给用户。
5 简述Django请求生命周期
一般是用户通过浏览器向我们的服务器发起一个请求(request),这个请求回去访问视图函数,(如果不涉及到数据调用,那么这个时候视图函数返回一个模板也就是一个网页给用户),视图函数调用模型,模型去数据库查找数据,然后逐级返回,视图函数把返回的数据填充到模板中空格中,最后返回网页给用户。
#1.wsgi,请求封装后交给web框架 (Flask、Django)
2.中间件,对请求进行校验或在请求对象中添加其他相关数据,例如:csrf、request.session -
#3.路由匹配 根据浏览器发送的不同url去匹配不同的视图函数
#4.视图函数,在视图函数中进行业务逻辑的处理,可能涉及到:orm、templates => 渲染 -
#5.中间件,对响应的数据进行处理。
#6.wsgi,将响应的内容发送给浏览器。
6 简述什么是FBV和CBV
FBV(function base views)就是在视图函面使用函数处理请求
CBV(class base views)就是在视图里面使用类处理请求
Django的url是将一个请求分配给可调用的函数的,而不是一个class。针对这个问题,class-based view提供了一个as_view()
静态方法(也就是类方法),调用这个方法,会创建一个类的实例,然后通过实例调用dispatch()
方法,dispatch()
方法会根据request的method的不同调用相应的方法来处理request(如get()
, post()
等)。到这里,这些方法和function-based view差不多了,要接收request,得到一个response返回。如果方法没有定义,会抛出HttpResponseNotAllowed异常。
7 django的版本
pip3 install django==1.11.9
8、启动django项目
django``-``admin startproject mysite
创建了一个名为"mysite"的Django 项目:
`python manage.py runserver ``8080 `
python manage.py startapp blog2 #每个应用都有自己的目录,每个应用的目录下都有自己的views.py视图函数和models.py数据库操作相关的文件
9 使用装饰器装饰 CBV
直接添加在dispatch里面,这样每个函数都会执行
from django.utils.decorators import method_decorator
@method_decorator(login_test)
def dispatch(self, request, *args, **kwargs):
res = super(IndexView, self).dispatch(request, *args, **kwargs)
return res
添加在每一个函数中
@method_decorator(login_test)
def get(self, request, *args, **kwargs):
return render(request, 'index.html')
直接添加在类上,后面的name表示只给get添加装饰器
@method_decorator(login_test, name='get') get是给get方法加 (以这种方式如果想给多个方法加装饰器,需要写多层装饰器,因为name这个参数的值必须是个字符串,并且不能同时写两个方法)
@method_decorator(login_test, name='post') post是给post方法加
class IndexView(View):
is_authenticated() 返回False 而不是True。
10 多个用户同时对一个公户进行操作的时候,如何处理?
判断是否contanant =null : 如果是,说明没人跟进,可以跟进
11 谈一谈你对ORM的理解
ORM是“对象-关系-映射”的简称。 (Object Relational Mapping,简称ORM)
MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因数据库变更而导致的无效劳动
用的什么数据库 ? mysql
InnoDB(表结构 数据+索引)
MySql 5.6 版本默认的存储引擎。InnoDB 是一个事务安全的存储引擎,它具备提交、回滚以及崩溃恢复的功能以保护用户数据。InnoDB 的行级别锁定以及 Oracle 风格的一致性无锁读提升了它的多用户并发数以及性能。InnoDB 将用户数据存储在聚集索引中以减少基于主键的普通查询所带来的 I/O 开销。为了保证数据的完整性,InnoDB 还支持外键约束。
MyISAM(表结构 纯数据 辅助索引)
MyISAM既不支持事务、也不支持外键、其优势是访问速度快,但是表级别的锁定限制了它在读写负载方面的性能,因此它经常应用于只读或者以读为主的数据场景。
InnoDB
用于事务处理应用程序,支持外键和行级锁。如果应用对事物的完整性有比较高的要求,在并发条件下要求数据的一致性,数据操作除了插入和查询之外,还包括很多更新和删除操作,那么InnoDB存储引擎是比较合适的。InnoDB除了有效的降低由删除和更新导致的锁定,还可以确保事务的完整提交和回滚,对于类似计费系统或者财务系统等对数据准确要求性比较高的系统都是合适的选择。
MyISAM
如果应用是以读操作和插入操作为主,只有很少的更新和删除操作,并且对事务的完整性、并发性要求不高,那么可以选择这个存储引擎。
Memory
将所有的数据保存在内存中,在需要快速定位记录和其他类似数据的环境下,可以提供极快的访问。Memory的缺陷是对表的大小有限制,虽然数据库因为异常终止的话数据可以正常恢复,但是一旦数据库关闭,存储在内存中的数据都会丢失。
12 自定义原生sql
def auth(username,password):
import pymysql
conn = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
password='123',
database='day53',
charset='utf8'
)
print('userinfo',username,password)
cursor = conn.cursor(pymysql.cursors.DictCursor)
sql = 'select * from userinfo where username=%s and password=%s;'
res = cursor.execute(sql, [username, password])
if res:
return True
原生的sql
raw()管理器方法用于原始的SQL查询,并返回模型的实例:
可以像下面这样执行原生SQL语句
这个方法执行原始的SQL查询,并返回一个django.db.models.query.RawQuerySet 实例。 这个RawQuerySet 实例可以像一般的QuerySet那样,通过迭代来提供对象实例。
>>> for p in Person.objects.raw('SELECT * FROM myapp_person'):
... print(p)
指定表名: 在model的class中,添加Meta类,在Meta类中指定表名db_table
13 orm项目的方法
聚合 aggregate
(*args, **kwargs) #Avg(``'price'``)
分组 annotate(c=Count("emp"))
F查询
``from` `django.db.models ``import` `F
``Book.objects.``filter``(commentNum__lt``=``F(``'keepNum'``))
Q查询
from` `django.db.models ``import` `Q
Q(title__startswith``=``'Py'``)
14 如何把全部信息都发过去
all() locals()
15 json
- JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
- JSON 是轻量级的文本数据交换格式
- JSON 独立于语言 *
- JSON 具有自我描述性,更易理解
JSON.parse(): 用于将一个 JSON 字符串转换为 JavaScript 对象
JSON.parse('{"name":"chao"}');
JSON.stringify(): 用于将 JavaScript 值转换为 JSON 字符串。
JSON.stringify({"name":"chao"})
return JsonResponse(ret, safe=False) 那边内置解释器就可以解析成浏览器可以识别的数据类型
16 ajax 的优点
1.AJAX使用JavaScript技术向服务器发送异步请求;
2.AJAX请求无须刷新整个页面;
3.因为服务器响应内容不再是整个页面,而是页面中的部分内容,所以AJAX性能高;
$("#b1").on("click", function () {
$.ajax({
url:"/ajax_add/", //别忘了加双引号
type:"GET",
data:{"i1":$("#i1").val(),"i2":$("#i2").val()}, //object类型,键值形式的,可以不给键加引号
success:function (data) {
$("#i3").val(data);
}
})
})
可以做错误提示
可以做角色用户的权限局部刷新
17 cookie 和session的区别
(1) 什么是Cookie
由于HTTP协议是无状态的,所以没有办法保持会话,基于这种情况,浏览器发展出了cookie技术,通过cookie就能够完成持续对话,大致过程就是类似一个字典的东西,从客户端浏览器访问服务的时候,带着这个字典,name后端服务器就能够身份认证的标识或者一些其他的信息,放到cookie里面,共客户端使用,并且以后客户端再来访问服务端就会一直带着这个cookie,后端就客户端的认证就可以从cookie里面的数据进行认证,从而完成保持会话的功能.
、如何获取、设置Cookiecookie
会话跟踪技术,保留用户
Cookie是由服务器创建,然?后通过响应发送给客户端?的一个键值对。
具体一个浏览器针对一个服务器存储的key-value({ })
response.set_cookie("is_login",True)
request.COOKIES.get("is_login")
(2) session
什么是session,与cookie的对比、设置、获取、清空session
Session是服务器端技术,利用这个技术,服务器在运行时可以 为每一个用户的浏览器创建一个其独享的session对象,由于 session为用户浏览器独享,所以用户在访问服务器的web资源时 ,可以把各自的数据放在各自的session中,当用户再去访问该服务器中的其它web资源时,其它web资源再从用户各自的session中 取出数据为用户服务。
request.session["is_login"] = True
is_login = request.session.get("is_login")
request.session.flush()
(3) session
过期时间 字节?
max_age: 后台控制过期时间
默认时长是2周,这个是以秒为单位的
cookie需要延续的时间(以秒为单位)
max_age=20秒 隔二十分钟注销
(4)cookie 的增删改查
rep.delete_cookie("user") 删
rep.set_cookie(key,value,...)
rep.get_cookie(key,value,...)
(5)session的增删改查
session.get['user'] = a /b 增或改
session.get['user'] 查
del request.session['k1']
# 删除当前会话的所有Session数据
request.session.delete()
# 删除当前的会话数据并删除会话的Cookie。
request.session.flush()
17 中间件
process_request(self,request) #请求来的时候,过中间件会自动执行的方法,正常的话,return None,异常的话直接可以回复HttpResponse对象,顺序从上之下执行
process_response(self, request, response) #响应回去会自动执行的方法,注意,return response 顺序从下往上倒序的.任意一个中间件的process_request方法里面如果出现了return一个HttpResponse对象,那么就会不继续执行其他内容了,而是直接执行各个中间件的process_response方法,如果自己的中间件里面有process_response这个方法,会先执行它自己的如果自己的中间件里面有process_response这个方法.直接返回.
process_view(self, request, view_func, view_args, view_kwargs) #url分发之后,视图执行之前,执行,从上到下正序的.
process_exception(self, request, exception) #视图函数报错了,会执行,顺序倒序的
process_template_response(self,request,response)#HttpResponse对象里面必须有个render函数,才会执行process_template_response方法,并且顺序是倒序的.并且render函数里面必须return一个HttpResponse对象,会将之前的覆盖掉
在哪里用到中间件
白名单 登录认证 权限 面包屑
19 formset
html
{{ formset.management_form }}
for 循环
py get
class Meta:
model = models.StudentStudyRecord
# fields = '__all__'
fields = ['score','homework_note']
class StudyRecordDetialView2(View):
def get(self,request,class_record_id):
all_study_record = models.StudentStudyRecord.objects.filter(
classstudyrecord=class_record_id,
)
form_set_obj = modelformset_factory(model=models.StudentStudyRecord,form=StudyRecordDetialModelForm)
formset = form_set_obj(queryset = all_study_record)
return render(request, 'student/study_record_detail.html', { 'formset': formset })
20 注册登录 认证
21 二级菜单如何做
22 setting 里的配置
数据库 DATABASE = []
中间件 middleware
认证 login_url = '/login/'
静态路径
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR,'statics'),
]
23 几个人开发的 多少天
内网:你写成啥样就啥样 谁提需求 : 销售
验证码是干啥
24 form 和 modermform 总结一下,其实form组件的主要功能如下:
form组件
生成页面可用的HTML标签
对用户提交的数据进行校验
保留上次输入内容
25 批量操作怎么处理
26 批量录入成绩
27 用过的过滤器
@login_request()
#这是一个简答的路由跳转测试
登录
datatime 分
过滤器 {{datime_obj|date:"Y-m-d H:i:s"}}
自定义标签 {%menu request%}
28 批量操作 一次性都把一个班转化为私户 一次性把10个大于90的传到跟进
29 所有的用户信息 发给前端
form.all() local()
30 form 和 modelform
一个个定义
crm 流程
#获取添加页面
def get(self,request):
form_obj = form.CustomerModelForm()
return render(request,'addcustomer.html',{'form_obj':form_obj})
def post(self,request):
form_obj = form.CustomerModelForm(request.POST)
#{'qq':'11111','name':'xiaohei'}
if form_obj.is_valid():
form_obj.save()
return redirect('customers')
31 如何将后端传送过来 前端class
给发送的前端数据里加一个{class:‘hide’}
def init ()
super(form表)
for field
field.upadate.attrs.
modelform类的写法
class BookForm(forms.ModelForm):
class Meta:
model = models.Book
fields = "__all__"
labels = {
"title": "书名",
"price": "价格"
}
widgets = {
"password": forms.widgets.PasswordInput(attrs={"class": "c1"}),
"publishDate": forms.widgets.DateInput(attrs={"type": "date"}),
}
32 modelform 钩子 和批量操作
验证 clean.data
class BookForm(forms.ModelForm):
def __init__(self,*args,**kwargs): #批量操作
super().__init__(*args,**kwargs)
for field in self.fields:
#field.error_messages = {'required':'不能为空'} #批量添加错误信息,这是都一样的错误,不一样的还是要单独写。
self.fields[field].widget.attrs.update({'class':'form-control'})
33 F和q查询
#F:对数据本身的不同字段进行操作 如:比较和更新,对数据进行加减操作
#Q:用于构造复杂的查询条件 如:& |操作
34 前后端验证
(前后端都要验证,前端效率高,后端也要)
前端form认证 后端钩子 clean_data 有不够字符的去除
35 注册登录
CRM(客户关系管理系统)
客户信息管理
1 引流 sem seo等
2 网络咨询师 大概介绍一下课程 让你留一些联系方式
潜在的客户信息登记到CRM里面 -- 公户 -- 私户
3 销售 ---聊,忽悠---
客户管理: 用户表 客户表 跟进记录表 报名表 缴费记录表
学员管理系统: 学生表 班级表 学习记录表 课程表 校区表
权限注入系统:
注册
form_obj = form.UserForm(request.POST)
if form_obj.is_valid():
data = form_obj.clean_data
pop('rpssword')
create_user(**data)
登录
user_objauth.authenticate(username=username,password=password)
# 3 保存session
auth.login(request,user_obj) #维持会话用的,
auth.logout(request)
增删改查不提问吗?
验证码
引入pillow画笔 给添加随机数字和噪点噪线
分页
传入 url , 页数
展示
#展示私有客户信息
def mycustomers(request):
my_customers = models.Customer.objects.filter(consultant=request.user)
return render(request, 'mycustomers.html', {'my_customers': my_customers})
添加 客户
class AddCustomer(View):
def get(self,request):
form_obj = form.CustomerModelForm()
return render(re ,'addcustomer.html',{'form_ob})
def post(self,request):
form_obj = form.CustomerModelForm(request.POST)
#{'qq':'11111','name':'xiaohei'}
if form_obj.is_valid():
form_obj.save()
return redirect('customers')
else:
return render(re ,'addcustomer.html',{'form_ob})
编辑:
class EditCustomer(View):
def get(self,request,pk):
custome_obj = models.Cmer.obs.filter(pk=pk)[0]
form_obj = form.CModelForm(instance=custome_obj)
return render(re,'editcu.html',{'form_obj':})
def post(self,request,pk):
custome_obj = models.Cmer.obs.filter(pk=pk)[0]
form_obj = form.CuModelForm(request.POST,instance=cust_obj)
# 防止后面save是创建
if form_obj.is_valid():
form_obj.save()
return redirect('customers')
else:
return render(re,'editcu.html',{'form_obj':})
删除
#删除单条公共客户信息
class DeleteCustomer(View):
def get(self,request,pk):
models.Customer.objects.filter(pk=pk).delete()
return redirect('customers')
整体的操作
-
ORM的内置函数Q()的经典用法
-
//通过.children.append向Q()对象中添加元组类型('field',condition)的筛选条件
<form action="" method="get" > <select name="condition" "> option value="name__contains">姓名</option> <option value="qq__contains">QQ</option> </select> <input type="text" name="wd" t">搜索</button> wd 和 condtion加到q.children()
批量删除 更改客户状态 批量公转私
#查看公户和私户客户西西里
class CustomerView(View):
def get(self,request):
wd = request.GET.get('wd','')
condition = request.GET.get('condition','')
#这是过滤公户的,也就是没有销售的
if request.path == reverse('customers'):
#过滤公户信息
flag = 0 #表示公户
all_customers = models.Customer.objects.filter(consultant__isnull=True)
else:
#过滤私户信息
flag = 1 # 表示私户
all_customers = models.Customer.objects.filter(consultant=request.user)
if wd:
q = Q()
# q.connector = 'or'
# q.children.append((condition,wd))
q.children.append((condition,wd))
#根据用户查询条件再次进行筛选
all_customers = all_customers.filter(q)
current_page_num = request.GET.get('page',1)
per_page_counts = 5
page_number = 11
total_count = all_customers.count()
page_obj = page.PageNation(request.path,current_page_num,total_count,request,per_page_counts,page_number)
all_customers = all_customers.order_by('-pk')[page_obj.start_num:page_obj.end_num]
ret_html = page_obj.page_html()
return render(request,'customers.html',{'all_customers':all_customers,'ret_html':ret_html,'flag':flag})
<td><input type="checkbox" name="selected_id" value="{{ customer.pk }}"></td>
<select name="action" id="" class="form-control" style="width: 200px;display: inline-block">
<option value="batch_delete">批量删除</option>
<option value="batch_update">批量更新客户状态</option>
def post(self,request):
print(request.POST)
self.data = request.POST.getlist('selected_id')
action = request.POST.get('action') #'batch_delete'
if hasattr(self,action):
func = getattr(self,action)
if callable(func):
ret = func(request)
if ret:
return ret
return redirect(request.path)
else:
return HttpResponse('不要搞事!!')
else:
return HttpResponse('不要搞事!!')
#批量删除
def batch_delete(self,request):
models.Customer.objects.filter(pk__in=self.data).delete()
#批量更新
def batch_update(self,request):
models.Customer.objects.filter(pk__in=self.data).update(name='雄哥')
#批量公户转私户
def batch_reverse_gs(self,request):
batch_customers = models.Customer.objects.filter(pk__in=self.data)
res = []
for i in batch_customers:
if i.consultant:
res.append(i)
else:
#更新数据的另一种方法,通过model对象来更新数据
i.consultant = request.user
i.save() #必须调用save才能保存
if res:
# return render()
ret_str = ','.join([(i.qq + ':' + i.name) for i in res])
return HttpResponse(ret_str)
batch_customers.update(consultant=request.user)
# # 批量私户转公户
def batch_reverse_sg(self, request):
models.Customer.objects.filter(pk__in=self.data).update(consultant=None)
跟进
#跟进记录的查询
class ConsultRecordView(View):
all_records = models.ConsultRecord.objects.filter(consultant=request.user)
return render(request, 'consultrecord.html',
{'all_records': all_records, 'ret_html': ret_html,})
跟进记录的添加和编辑 zoude yige url
class AddConsultRecordView(View):
def get(self,request,pk=None):
consultrecordobj = models.ConsultRecord.objects.filter(pk=pk).first()
form_obj = form.ConsultRecordModelForm(request,instance=consultrecordobj)
return render(request,'addconsultrecord.html',{'form_obj':form_obj})
def post(self,request,pk=None):
consultrecordobj = models.ConsultRecord.objects.filter(pk=pk).first()
form_obj = form.ConsultRecordModelForm(request,request.POST,instance=consultrecordobj) #QueryDict
if form_obj.is_valid():
form_obj.save()
return redirect('consultrecord')
else:
return render(request,'addconsultrecord.html',{'form_obj':form_obj})
36 权限
6张表 user : role: 销售讲师ceo permission 一级菜单表
多对多 user role role 和permission
之后由于做二级菜单修改了表结构
不同的人登录显示不同的功能 操作的
左侧菜单 增删改查
批量录入
formset 新建一个modelform的表
继承修改的字段
all_student
formset = model = 表 form=新表
formset = queryset = all_studnet
return
中间件 --》 login 白名单放行 sesion保存 登录信息
权限注入 url权限注入 [{pk},{url}] 菜单权限注入 {children:{}}
inclusiontag menu_html 判断
面包屑
权限批量更改
ajax
37 auth模块
- 创建用户
python manage.py createsuperuser
python manage.py createuser
- 模块的导入:
from django.contrib import auth
- auth中提供的实用方法:
1. authenticate()
提供了用户认证功能,即验证用户名以及密码是否正确,一般需要username 、password两个关键字参数。如果认证成功(用户名和密码正确有效),便会返回一个 User 对象。authenticate()会在该 User 对象上设置一个属性来标识后端已经认证了该用户,且该信息在后续的登录过程中是需要的。
user = authenticate(username='theuser',password='thepassword')
2.login(HttpRequest, user)
该函数接受一个HttpRequest对象,以及一个经过认证的User对象。该函数实现一个用户登录的功能。它本质上会在后端为该用户生成相关session数据
from django.contrib.auth import authenticate, login
def my_view(request):
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
# Redirect to a success page.
...
else:
# Return an 'invalid login' error message.
...
3.logout(request)
该函数接受一个HttpRequest对象,无返回值。当调用该函数时,当前请求的session信息会全部清除。该用户即使没有登录,使用该函数也不会报错。
from django.contrib.auth import logout
def logout_view(request):
logout(request)
# Redirect to a success page.
4.is_authenticated()
用来判断当前请求是否通过了认证
def my_view(request):
if not request.user.is_authenticated():
return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
5.login_requierd()
auth 给我们提供的一个装饰器工具,用来快捷的给某个FBV视图添加登录校验。
from django.contrib.auth.decorators import login_required
@login_required
def my_view(request):
...
37 页面上有没有存聊天记录 如何记录
38 自定义标签的过程
templatetags 自定义文件夹
from django import template
register = template.Library()
@register.simple_tag
@register.inclusion_tag('rbac/menu.html')
39 权限分配
基于ajax 的权限认证