自定义验证类
在views.py中
#由于django只验证用户名,密码,因此需要自定义
class CustomBackend(ModelBackend):
def authenticate(self, request, username=None, password=None, **kwargs):
try:
user = User.objects.get(
Q(username=username) |
Q(email=username ) |
Q(mobile = username)
)
if user.check_password(password):
return user
except Exception:
return None
#值得注意的地方,用于验证的字段必须不能重复,而且不能为空
小技巧
测试单个文件
#单独测试某模块的功能
import os, sys
# 获取到项目的根目录
PROJECT_ROOT = os.path.dirname(os.path.abspath('__file__')) #根据具体的文件位置改变
# 把项目的根目录放到 sys.path 中
sys.path.insert(0, PROJECT_ROOT)
# 设置环境变量
os.environ["DJANGO_SETTINGS_MODULE"] = 'qf01.settings'
import django
django.setup()
if __name__ == "__main__":
"""在这里写自己的测试代码"""
# 导入 映射类
from users.models import UsersProfile
# 获取表中的第一条数据
user = UsersProfile.objects.all()[1]
print(user.username, user.mobile)
前后端分离---后端发送JSON数据
from django.http import JsonResponse,HttpResponse
from django.views import View
from django.core import serializers
from users.models import UsersProfile
from cmdb.models import Server
class ApiView(View):
def get(self, request):
users = Server.objects.values()
return JsonResponse(list(users), safe=False)
#json数据里直接为得到的数据的字典,safe为必须字段
class ApiViewTwo(View):
def get(self, request):
users = UsersProfile.objects.all()
data = serializers.serialize('json',users)
return HttpResponse(data)
#json数据为字典嵌套字典,字段为某一vales
前后段分离---urls
from django.urls import path
from . import views
from django.views.generic import TemplateView
app_name = "api"
urlpatterns = [
path('users-json/', views.ApiView.as_view(), name="user2json"),
path('users-json2/', views.ApiViewTwo.as_view(), name="user2json2"),
path('users-json3/', views.ApiViewThree.as_view(), name="jQuery"),
path('server-vue/', TemplateView.as_view(template_name="api/VueAxios.html"), name='VueAxios'), #不需要在views中写,直接返回页面
]
#使用template可以不要在views.py中写class,直接返回页面,因此无法做到登陆用户验证
前后端分离---前端接收
方式一
{% extends 'putbase.html' %}
{% block content %}
<button type="submit" id = 'btn' class="btn btn-success" >获取数据</button>
<h2 id="title"></h2>
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>id</th>
<th>主机名</th>
<th>操作系统</th>
<th>物理 CPU 颗数</th>
</tr>
</thead>
<tbody id = "mess">
</tbody>
</table>
{% endblock %}
{% block script %}
<script>
$(function(){
let title_tg = $("#mess")
$("#btn").on("click",function(){
$.ajax({ #ajax的固定格式
url: "{% url 'api:user2json' %}", #数据来源
type: 'GET', #请求数据的方式
dataType: 'json', #数据格式
success:function (res) { #若请求成功则执行
for (let i of res){
title_tg.append(`<tr> #将循环得到的数据添加到tbody中,使用append方法不
<td>${i.id}</td> #会覆盖上一条数据,但是每点击一次请求,就会get
<td>${i.host_name}</td> #一次。
<td>${i.os_name}</td>
<td>${i.physical_count}</td> #`<>${}<>`添加标签
</tr>`)
// title_tg.html() #将`<>${}<>`的标签添加到html中
}
},
});
})
})
</script>
{% endblock %}
方式二
#使用vue与axios结合的方式
{% extends 'putbase.html' %}
{% block content %}
<div id="app">
{% verbatim %}
<button id="btn" class="btn btn-success">获取数据</button>
<h2>Vue出现{{ msg }}</h2>
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>id</th>
<th>主机名</th>
<th>内核</th>
<th>物理 CPU 颗数</th>
</tr>
</thead>
<tbody id="tbody">
<tr v-for="item in servers" :key=""> #vue循环
<td>{{ item.id }}</td>
<td>{{ item.host_name }}</td>
<td>{{ item.kernel }}</td>
<td>{{ item.physical_count }}</td>
</tr>
</tbody>
</table>
{% endverbatim %}
</div>
{% endblock %}
{% block script %}
<script>
var app = new Vue({
el: "#app",
data: {
msg: 'hello',
servers: ''
},
mounted() {
axios.get(
"{% url 'api:user2json' %}",
).then(
res => {
this.servers = res.data;
});
},
})
</script>
{% endblock %}
将vue,axios,bootstrap,加载到本地文件中
#在项目主目录里建立static目录
/django2-demo/roudjo/statics/
├── bootstrap
│ ├── css
│ ├── fonts
│ └── js
└── js
├── axios.min.js
└── vue.min.js
#在setttings.py中
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'statics'), # 最后有英文的逗号
]
#在前端页面中
##############################################################
方式一:
href="/static/bootstrap/css/bootstrap.min.css"
#/static为STATIC_URL的指定名字 后面为项目文件名字
###############################################################
方式二:
{% load staticfiles %} #在<head>是上面添加
src="{% static 'js/axios.min.js' %}" #static同样为STATIC_URL的指定名字 ,后面为项目文件名字
中间件
http的请求通过的顺序

自定义中间件
#在项目主目录下建立中间件目录
/django2-demo/roudjo/MyMiddieware/
├── __pycache__
└── rejectip.py
#在rejectip.py中
from django.shortcuts import HttpResponse
import time
# 时间范围 3 秒
REJ_SECOND = 5
# 限定访问次数
REJ_LIMIT = 3
# 封闭时长
REJ_TIME = 10
# IP 列表
REJ_IP = {}
info = {
'count': '3 秒内范围的次数',
'access_time': '访问时间',
'rejected': '拒绝时长',
}
def reject_ip(ip):
if ip not in REJ_IP:
REJ_IP[ip] = {
'count': 1,
'access_time': int(time.time()),
'rejected': None
}
return None
# 程序走到这里时,增加访问次数 1 次
REJ_IP[ip]['count'] += 1
# 判断是否在 3 秒之内
if time.time() < REJ_IP[ip]['access_time'] + 3:
# 判断访问次数合法
if REJ_IP[ip]['count'] > REJ_LIMIT:
REJ_IP[ip]["rejected"] = int(time.time())
print("访问次数首次超限:",REJ_IP[ip]['count'])
return True
print("有了:",REJ_IP)
# 程序走的这里是 3 秒之外
else:
print("目的访问次数:",REJ_IP[ip]['count'])
rejected = REJ_IP[ip]["rejected"]
if rejected and time.time() < REJ_IP[ip]["rejected"] + REJ_TIME:
print("访问信息",REJ_IP[ip] )
return True
else:
# 3 秒之外了,并且没有被封,或者超出解禁时间范围的,
# 次数和时间都应该重新计算
print("来了兄弟", REJ_IP, int(time.time()))
__tmp_d = {'count': 1,
'rejected': None,
'access_time': int(time.time())}
REJ_IP[ip].update(__tmp_d)
print("改过了", REJ_IP)
class RejectIpMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
remote_ip = request.META['REMOTE_ADDR']
# print(f"接收到请求后 --> 我在这里呀{remote_ip}--》调用视图前")
if reject_ip(remote_ip):
return HttpResponse(f"访问受限")
response = self.get_response(request)
# print("调用视图后--》我在这里呀--》返回页面前")
return response
#在settings.py中
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'MyMiddieware.rejectip.RejectIpMiddleware', #确定中间件的添加位置
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
详细过程

1.用户通过浏览器请求一个页面
2.请求到达Request Middlewares,中间件对request做一些预处理或者直接response请求
3.URLConf通过urls.py文件和请求的URL找到相应的View
4.View Middlewares被访问,它同样可以对request做一些处理或者直接返回response
5.调用View中的函数
6.View中的方法可以选择性的通过Models访问底层的数据
7.所有的Model-to-DB的交互都是通过manager完成的
8.如果需要,Views可以使用一个特殊的Context
9.Context被传给Template用来生成页面
a.Template使用Filters和Tags去渲染输出
b.输出被返回到View
c.HTTPResponse被发送到Response Middlewares
d.任何Response Middlewares都可以丰富response或者返回一个完全不同的response
e.Response返回到浏览器,呈现给用户
网友评论