慕课DJANGO配置
重写内置的错误处理视图
在项目urls.py中添加配置
handler500 = "app01.views.page_500"
handler404 = "app01.views.page_404"
handler403 = "app01.views.page_403"
在项目视图中如下填写
from django.core.exceptions import PermissionDenied def test(request):
# raise ValueError
raise PermissionDenied
return HttpResponse('ok') def page_500(request):
return HttpResponse('500') def page_404(request):
return HttpResponse('404') def page_403(request):
return HttpResponse('403')
切换到生产模式DEBUG=False
STATIC处理静态文件
在项目settings.py中添加配置 STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
]
在项目settings.py中添加配置 MEDIA_URL='/media/'
MEDIA_ROOT=os.path.join(BASE_DIR,'medias')
在项目urls中添加配置 from django.views.static import serve
from django.conf import settings urlpatterns += [
url(r'^medias/(?P<path>.*)$',serve,{
'document_root':settings.MEDIA_ROOT,
}),
]
请求对象HttpRequest
请求头信息META
REMOTE_ADDR------请求的IP地址
HTTP_USER_AGENT-----用户请求终端信息
常见的Content-Type
text/html——超文本标记语言文本(HTML)
text/plain——普通文本 text/xml——XML文档
image/png、image/jpeg、image/gif——图片或图形
application/json ——json数据类型
响应对象
HttpResponse
HttpResponseRedirect
JsonResponse——响应json
FileResponse——响应文件
HttpResponse
status查看HTTP响应状态码
status_code查看HTTP响应状态码
content_type设置响应的类型
write()写入响应内容
def content(request):
dic = {
'username':'jamie',
}
# return HttpResponse('ok',content_type='text/plain')
import json
ret = json.dumps(dic)
# return HttpResponse(ret,content_type='application/json')
return JsonResponse(dic) def status(request):
# 改变响应状态码
ret = HttpResponse('status_code', status=404)
# 重新设置HTTP的状态码
ret.status_code = 200
# 打印HTTPS状态码
print(ret.status_code)
# 写入响应内容
ret.write('多写入响应内容')
return ret def image(request):
# pring image
import os
from django.conf import settings
try:
file_name = os.path.join(settings.BASE_DIR,'medias/images/1111.png')
f = open(file_name, 'rb')
except Exception as e:
print(e)
return FileResponse(f,content_type='image/png')
# application/vnd.ms-excel 这样可以导出EXCEL
使用CLASS重写视图
url(r'^class/',views.classview.as_view(), name='class'), from django.views.generic import TemplateView class classview(TemplateView):
'''class'''
template_name = 'class.html'
渲染机制
1. 从磁盘读取html字符串
2. 将满足特定规则的内容进行替换 3. 发送给浏览器展示
步骤一:从磁盘读取模板文件(get_template)
步骤二:选择合适的模板引擎(select_template)
步骤三:将制定内容对模板进行渲染(render)
步骤四:发送给浏览器显示
配置选项
APP_DIRS——决定模板引擎是否应该进入每个已安装 的应用中查找模板
每种模板引擎后端都定义了一个惯用的名称作为应用内部存放 模板的子目录名称
DTL——templates目录
Jinja2——jinja2目录
OPTIONS——其他选项配置
同时支持俩种引擎模板
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'mine.context_processors.const',
],
},
},
{
'BACKEND': 'django.template.backends.jinja2.Jinja2',
'DIRS': [os.path.join(BASE_DIR, 'jiaja2')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
渲染静态图片
img_url = "/medias/images/1111.png"
return render(request,'image1.html',{'img_url':img_url})
<img src="{{ img_url }}" alt="403报错图片">
模板标签的使用
循环控制
{% for item in data_list %} <li>内容</li>
{% endfor %}
条件控制
{% if condition_a %} 满足了A条件
{% elif condition_b %} 满足了B条件
{% else %} 都不满足
{% endif %}
注释
添加注释
{# 注释内容 #}
与HTML注释的区别
<!-- 注释内容 -->
重复循环
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.row1 {
background-color: pink;
}
.row2 {
background-color: red;
}
.row3 {
background-color: gray;
}
</style>
</head>
<body> <ul>
{% for foo in tag reversed%}
<li class="{% cycle 'row1' 'row2' 'row3' %}">{{ forloop.counter }}{{ foo }}</li>
{% empty %}
<li>列表要是空就走这里</li>
{% endfor %}
</ul> </body>
</html>
过滤器:对变量进行特殊处理后再渲染?
过滤器语法
{{ value|filter_name: params }}
使用过滤器将字母大写
{{ value|upper}}
内置过滤器
def test_tp_filter(request):
import math
pi = math.pi
html = '<h1>lalalalalalalalala</h1>'
import datetime
time = datetime.datetime.now()
user_info = {
'username': 'jamie',
'age': None,
'sex': False,
'pi': pi,
'html': html,
'time': time
}
return render(request, 'filter.html', {'userinfo': user_info})
日期对象格式化
{{ value|date:"D d M Y" }}
默认值显示
{{ value|default:"" }} # 为none时候显示我
{{ value|default_if_none:“无" }} # 为空false显示我
数字四舍五入显示
{{ value | floatformat:3 }}
富文本内容转义显示
{{ value|safe }}
字符串截取
{{ value|truncatechars:9 }}
{{ value|truncatechars_html:9 }} # 不算Html字符
{{ value|truncatewords:2 }}
自定义过滤器
步骤一:在app目录下新建包templatetags
polls/
__init__.py
models.py
templatetags/
__init__.py
poll_extras.py
views.py 步骤二:实现过滤器poll_filter.py
from django import template
register = template.Library() def warning(value):
""" 将第一个字符变红 """
return '<span class="red">' + value[0] +'</span>'+ value[1:] register.filter('warning', warning) 步骤三:在模板中使用过滤器
{% load poll_filter %}
{{ value| warning|safe }}
切记:添加自定义过滤器后记得重启开发服务器
模板抽象和继承
步骤一:将可变的部分圈出来(base.html)
{% block sidebar %}
<!--菜单栏的内容 -->
{% endblock %} 步骤二:继承父模板
{% extends "base.html" %} 步骤三:填充新的内容(index.html)
{% extends "base.html" %}
{% block sidebar %}
<!-- 新的菜单栏的内容 -->
{% endblock %} 步骤四:复用父模板的内容(可选)
{% extends "base.html" %} {% block sidebar %}
{{ supper }}
<!-- 新的菜单栏的内容 -->
{% endblock %}
在模板中添加公共部分
步骤一:将可变的部分拆出来(footer.html)
<footer>
这是页脚公共的部分
</footer> 步骤二:将拆出来的部分包进来(index.html)
{% extends "base.html" %}
{% block content %}
<!– 页面主要内容区域-->
{# 公用的footer #}
{% include "footer.html" %}
{% endblock %}
Django工具及管理
常用的内置命令(mine是一个app应用)
检查djangoORM模型
python manage.py check
生成同步原语
python manage.py makemigrations
模型同步
python manage.py migrate
收集依赖中的静态文件
python manage.py collectstatic
django控制台
python manage.py shell
清除过期会话
python manage.py clearsessions
自定义Django命令行工具
第一步:创建指定的目录及文件结构
mine/
__init__.py
models.py
management/
__init__.py
commands/
__init__.py
update.py
urls.py
views.py 第二步:实现自定义命令
实现django.core.management.base.BaseCommand的子类
添加命令参数add_arguments
处理命令逻辑handle
显示处理过程(self.stdout.write/self.stderr.write) """
update.py
更新订单状态 订单超过半小时不支付,取消订单,释放库存
"""
from django.core.management.base import BaseCommand class Command(BaseCommand):
help = """
更新订单状态
回收订单 """ def add_arguments(self, parser):
"""
添加命令的参数
argparse
https://docs.python.org/3/library/argparse.html 1. 回收所有超时未支付的订单
python manage.py update --all
2. 指定回收某一个订单
python manage.py update --one 20001
:param parser:
:return:
"""
# 添加参数 dest匹配参数,交给handel处理,
parser.add_argument(
'--all',
# 不需要加参数的意思,但是还没确定
action='store_true',
dest='all',
default=False,
help='回收所有超时未支付的订单'
) parser.add_argument(
'--one',
action='store',
dest='one',
default=False,
help='指定回收某一个订单'
) def handle(self, *args, **options):
if options['all']:
self.stdout.write('开始回收订单')
# 逻辑处理
self.stdout.write('-------')
self.stdout.write('处理完成')
elif options['one']:
self.stdout.write('开始回收订单{}'.format(options['one']))
else:
self.stderr.write('指令异常')
Django中间件的开发和使用
上下文处理器,为模板添加全局变量,utils是创建在项目里面的公用脚本目录
渲染上下文Context
请求上下文RequestContext
连接views(视图)和templates(模板)
场景举例: 在每个页面都显示IP地址,多个页面展示购物车信息 TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'mine.context_processors.const', # 这里定义上下文的路径
],
},
},
] from utils import constants
def const(request):
addr = '湖南'
return {
'constants': constants.UserList,
'addr':addr,
} # Utils是个创建在项目下的目录
# !/usr/bin/env python
# _*_ coding:utf-8 _*_
# Author: Jamie UserList = ['吊哥','傻逼'] 模板调用
{% for foo in constants %}
{{ foo }}
{% endfor %} {{ addr }}
中间件,过滤请求,拦截请求
场景1:用户非法请求拦截
添加IP地址黑名单,在名单内的用户限制访问
场景2:模拟用户登录
实现简单的用户登录中间件 步骤一:实现中间件,处理业务逻辑
方式1:函数式自定义中间件
方式2: OOP(面向对象)自定义中间件
步骤二:激活中间件,添加到setting.py配置 '''
保存在Utils目录里面,公共方法,ip_middleware.py
'''
from django.http import HttpResponse
from weibo.models import WeiboUser def ip_middleware(get_response): def middleware(request): # 请求到达前的业务逻辑
print('请求到达前的业务逻辑')
# 请求不满足业务规则:IP被限制
ip = request.META.get('REMOTE_ADDR', None)
ip_disable_list = [
'127.0.0.1'
]
print(ip)
# for ip_dis in ip_disable_list:
# if ip_dis == ip:
if ip in ip_disable_list:
return HttpResponse('not allowed', status=403)
reponse = get_response(request) # 在视图函数调用之后的业务逻辑
print('在视图函数调用之后的业务逻辑')
return reponse return middleware class MallAuthMiddleware(object):
""" 自定义的登录验证中间件 """ def __init__(self, get_response):
self.get_response = get_response def __call__(self, request, *args, **kwargs):
print('MallAuthMiddleware请求到达前的业务逻辑')
# 请求不满足业务规则:IP被限制 user_id = request.session.get('user_id', None)
print('middle:%s' %user_id)
if user_id:
user = WeiboUser.users.get(pk=user_id)
else:
user = None request.my_user = user
print('--------------', user)
reponse = self.get_response(request) # 在视图函数调用之后的业务逻辑
print('MallAuthMiddleware在视图函数调用之后的业务逻辑')
return reponse MIDDLEWARE = [
# 'debug_toolbar.middleware.DebugToolbarMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
# 'utils.middleware.ip_middleware',
'utils.middleware.MallAuthMiddleware'
]
另一篇实例 https://www.cnblogs.com/jokerbj/p/8173820.html
Django扩展
DRF(Django REST Framework)REST接口框架
django-cms 内容管理系统
django-debug-toolbar 调试工具 pypi.org搜索,要对应JDANGO版本
django-channels Websocket通信
表单重复提交
BUG邮件通知
1.发送文字邮件
2.发送HTML邮件
3.发送带附件的邮件
4.发送多个邮件
5.打破连接限制,连接复用 第一步:邮件配置
第二步:准备邮件内容
第三步:发送邮件 '''
SETTINGS.PY
'''
# 邮件发送配置
EMAIL_HOST = 'smtp.qq.com'
EMAIL_HOST_USER = 'navcat@foxmail.com'
EMAIL_HOST_PASSWORD = 'vgppwryinupwbfgb'
# 自己发送,from django.core.mail import send_mail send_mail(邮件主题,邮件内容,发件人,发送给谁,是个列表) # 触发异常就会给ADMINS发邮件,DEBUG = False
SERVER_EMAIL = 'navcat@foxmail.com'
ADMINS = [('admin', 'navcat@foxmail.com')]
https://docs.djangoproject.com/en/1.11/topics/email/
日志记录配置
logging的四个部分
1.Loggers——日志记录入口
2.Handlers——决定处理logger中消息的方式
3.Filters——对日志进行条件控制
4.Formatters——日志记录的文本顺序(格式) Logger的级别
DEBUG:用于调试目的的底层系统信息
INFO:普通的系统信息
WARNING:警告,较小的问题,不影响执行顺序
ERROR:错误,较大的问题 CRITICAL:严重,致命的问题 '''
SETTINGS.PY
'''
# 日志的配置
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
},
'simple': {
'format': '%(levelname)s %(message)s'
},
},
'handlers': {
'sql_log_file': {
'level': 'DEBUG',
'class': 'logging.FileHandler',
'filename': os.path.join(BASE_DIR, 'log/sql.log'),
},
'log_index_file': {
'level': 'DEBUG',
'class': 'logging.FileHandler',
'formatter': 'verbose',
'filename': os.path.join(BASE_DIR, 'log/index.log'),
},
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
# 'formatter': 'simple'
},
'mail_admins': {
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailHandler',
# 'filters': ['special']
}
},
'loggers': {
'django.db.backends': {
'handlers': ['sql_log_file',],
'level': 'DEBUG',
'propagate': True,
},
'index': {
'handlers': ['log_index_file', 'console'],
'level': 'DEBUG',
}
},
}
上传图片方式
# !/usr/bin/env python
# _*_ coding:utf-8 _*_
# Author: Jamie import re
from django import forms
from weibo import models
class UserLoginForm(forms.Form):
username = forms.CharField(label='用户名',max_length=64)
password = forms.CharField(label='密码',max_length=64,widget=forms.PasswordInput)
verify_code = forms.CharField(label='验证码',max_length=64) def clean_username(self):
username = self.cleaned_data['username']
pattern = r'^0{0,1}1[0-9]{10}$'
if not re.search(pattern,username):
raise forms.ValidationError('请输入正确的手机号码')
return username def clean(self):
cleand_data = super().clean()
username = cleand_data.get('username',None)
password = cleand_data.get('password',None)
if username and password:
user_list = models.WeiboUser.users.filter(username=username)
if user_list.count() == 0:
raise forms.ValidationError('用户名不存在')
if not user_list.filter(password=password).exists*():
raise forms.ValidationError('密码错误')
return cleand_data class UserForm(forms.ModelForm):
class Meta:
model = models.WeiboUser
fields = ['username','password']
widgets = {
'password':forms.PasswordInput(attrs={
'class':'text-error',
})
}
labels = {
'username':'手机号码',
}
error_messages = {
'username':{
'required':'请输入手机号码',
'max_length':'最长不超过32',
}
} class AvatarUploadForm(forms.Form):
remark = forms.CharField(label='备注',max_length=32)
touxiang = forms.FileField(label='头像') class WeiboImageForm(forms.ModelForm):
content = forms.CharField(label='微博内容',max_length=256,widget=forms.Textarea(attrs={'placeholder':'请输入微博内容'}))
class Meta:
model = models.WeiboImage
fields = ['image'] def save(self,user,commit=False):
obj = super().save(commit)
data = self.cleaned_data
content = self.cleaned_data['content']
#1 创建微博记录
weibo = models.Weibo.objects.create(user=user,content=content)
#2 修改微博关联关系
obj.weibo = weibo
obj.save()
return obj
FORMS
def upload_one(request):
if request.method == 'POST':
file = request.FILES.get('touxiang',None)
import os
from dalaohu import settings
filename = os.path.join(settings.MEDIA_ROOT,'touxiang')
with open(filename,'wb+') as f:
for i in file.chunks():
f.write(i)
print('上传陈功了')
return render(request,'upload_one.html') def upload_two(request):
if request.method == 'POST':
form = forms.AvatarUploadForm(request.POST,request.FILES)
if form.is_valid():
file = request.FILES.get('touxiang', None)
import os
from dalaohu import settings
filename = os.path.join(settings.MEDIA_ROOT, 'touxiang1')
with open(filename, 'wb+') as f:
for i in file.chunks():
f.write(i)
print('上传陈功了')
else:
form = forms.AvatarUploadForm()
return render(request,'upload_two.html',{'form':form}) def upload_three(request):
if request.method == 'POST':
user = WeiboUser.users.get(pk=1)
form = forms.WeiboImageForm(request.POST,request.FILES)
if form.is_valid():
obj = form.save(user,False)
print('保存陈功了',obj.pk)
else:
form = forms.WeiboImageForm()
return render(request,'upload_three.html',{
'form':form
})
VIEWS
自带登录验证
import re from django import forms
from django.forms import widgets
from django.forms import fields
from django.contrib.auth import authenticate, login
from django.contrib.auth.models import User from utils.verify import VerifyCode class UserLoginForm(forms.Form):
""" 用户登录表单 """
username = forms.CharField(label='用户名', max_length=64,widget=widgets.TextInput(attrs={'class':'form-control','placeholder':'请输入用户名'}),
error_messages={
'required': '请输入用户名',
}
)
password = forms.CharField(label='密码', max_length=64,widget=widgets.PasswordInput(attrs={'class':'form-control','placeholder':'请输入密码'}),
error_messages={
'required': '请输入密码',
})
verify_code = forms.CharField(label='验证码', max_length=4,widget=widgets.TextInput(attrs={'class':'form-control','placeholder':'验证码'}),
error_messages={
'required': '请输入验证码',
}) def __init__(self, request, *args, **kwargs):
super().__init__(*args, **kwargs)
self.request = request # def clean_username(self):
# """ 验证用户名 hook 钩子函数"""
# username = self.cleaned_data['username']
# print(username)
# # 判断用户名是否为手机号码
# pattern = r'^0{0,1}1[0-9]{10}$'
# if not re.search(pattern, username):
# raise forms.ValidationError('请输入正确的手机号码')
# return username def clean_verify_code(self):
""" 验证用户输入的验证码是否正确 """
verify_code = self.cleaned_data['verify_code']
if not verify_code:
raise forms.ValidationError('请输入验证码')
client = VerifyCode(self.request)
if not client.validate_code(verify_code):
raise forms.ValidationError('验证码不正确')
return verify_code def clean(self):
cleaned_data = super().clean()
print(cleaned_data)
# 获取用户名和密码 ,不建议使用[]的方式
# username = cleaned_data['username'] username = cleaned_data.get('username', None)
password = cleaned_data.get('password', None)
if username and password:
# 查询用户名和密码匹配的用户
user_list = User.objects.filter(username=username)
if user_list.count() == 0:
raise forms.ValidationError('用户名不存在')
# # 验证密码是否正确
# if not user_list.filter(password=password).exists():
# raise forms.ValidationError('密码错误')
if not authenticate(username=username, password=password):
raise forms.ValidationError('密码错误')
return cleaned_data class UserRegistForm(forms.Form):
""" 用户注册表单 """
username = forms.CharField(label='用户名', max_length=64)
nickname = forms.CharField(label='昵称', max_length=64)
password = forms.CharField(label='密码', max_length=64, widget=forms.PasswordInput)
password_repeat = forms.CharField(label='重复密码', max_length=64, widget=forms.PasswordInput)
verify_code = forms.CharField(label='验证码', max_length=4) def __init__(self, request, *args, **kwargs):
super().__init__(*args, **kwargs)
self.request = request def clean_username(self):
""" 验证用户名是否已经被注册 """
data = self.cleaned_data['username']
if User.objects.filter(username=data).exists():
raise forms.ValidationError('用户名已存在')
return data def clean_verify_code(self):
""" 验证用户输入的验证码是否正确 """
verify_code = self.cleaned_data['verify_code']
if not verify_code:
raise forms.ValidationError('请输入验证码')
client = VerifyCode(self.request)
if not client.validate_code(verify_code):
raise forms.ValidationError('您输入的验证码不正确')
return verify_code def clean(self):
cleaned_data = super().clean()
password = cleaned_data.get('password', None)
password_repeat = cleaned_data.get('password_repeat', None)
if password and password_repeat:
if password != password_repeat:
raise forms.ValidationError('两次密码输入不一致')
return cleaned_data def register(self):
""" 注册方法 """
data = self.cleaned_data
# 1. 创建用户
User.objects.create_user(username=data['username'],
password=data['password'],
level=0,
nickname='昵称')
# 2. 自动登录
user = authenticate(username=data['username'],
password=data['password'])
login(self.request, user)
return user
FORMS
from django.contrib.auth import authenticate, login, logout
from utils.verify import VerifyCode
from weibo.forms import UserLoginForm,UserRegistForm
from django.contrib.auth.models import User
def user_add(request):
'''创建用户'''
user = User.objects.create_user('liqianlong','lal@126.com',123456)
return HttpResponse('创建账号成功') def user_login1(request):
""" 用户登录 """
# 如果登录是从其他页面跳转过来的,会带next参数,如果有next参数,登录完成后,需要调转到
# next所对应的地址,否则,跳转到首页上去
next_url = request.GET.get('next', 'weibo:index') if request.method == 'POST':
form = UserLoginForm(request=request, data=request.POST)
# print(request.POST)
# client = VerifyCode(request)
# code = request.POST.get('verify_code', None)
# rest = client.validate_code(code)
# print('验证结果:', rest)
# 表单是否通过了验证
if form.is_valid():
# 执行登录
data = form.cleaned_data # ## 使用自定义的方式实现登录
# # 查询用户信息 [MD5]加密算法,不可逆的加密算法 1243 -> sdfadfad
# user = User.objects.get(username=data['username'], password=data['password'])
# # 设置用户ID到session
# request.session[constants.LOGIN_SESSION_ID] = user.id
# # 登录后的跳转
# return redirect('index') ### 使用django-auth来实现登录
user = authenticate(request, username=data['username'], password=data['password'])
print('view:%s' %user.id)
if user is not None:
### 为了测试自定义中间件加的session
request.session['user_id'] = user.id
login(request, user)
# 登录后的跳转
return redirect(next_url)
else:
print(form.errors)
else:
form = UserLoginForm(request)
return render(request, 'login.html', {'form': form,'next_url':next_url}) def user_logout(request):
""" 用户退出登录 """
logout(request)
return redirect('weibo:user_login1') import logging
logger = logging.getLogger('index')
logger.debug('调试信息')
logger.info('普通信息')
logger.error("异常") @login_required
def index(request):
# 记录调试信息
print('登录成功,打开首页',request.my_user)
return render(request,'wbindex.html') def user_register(request):
""" 用户注册 """
if request.method == 'POST':
form = UserRegistForm(request=request, data=request.POST)
if form.is_valid():
# 调用注册方法
form.register()
return redirect('index')
else:
print(form.errors)
else:
form = UserRegistForm(request=request)
return render(request, 'register.html', {
'form': form
}) def code(request):
client = VerifyCode(request)
return client.gen_code()
VIEWS
# 用户登录
url(r'^user/user_add/$', views.user_add, name='user_add'),
url(r'^user/login/$', views.user_login1, name='user_login1'),
# 用户退出
url(r'^user/logout/$', views.user_logout, name='user_logout'),
# 用户注册
url(r'^user/register/$', views.user_register, name='user_register'),
# 验证码
url(r'^user/code/$', views.code, name='verify_code'),
# index
url(r'^user/index/$', views.index, name='index'),
URLS
"""
生成验证码:
1. 准备素材
字体(ttf),文字内容,颜色,干扰线
2. 画验证码
pip install Pillow 、random
创建图片
记录文字内容,django session【服务器,python代码】
abcdefg cookie 【浏览器】 (1) 第一次请求,cookie + session 对应关系生成
(2) 第二次请求,携带了cookie,找到对应的session【提交表单】
请求带上验证码参数 与 session中的验证码进行比较
3. io文件流
BytesIO
"""
import random import os from PIL import Image, ImageDraw, ImageFont
from django.conf import settings
from io import BytesIO from django.http import HttpResponse class VerifyCode(object):
""" 验证码类 """ def __init__(self, dj_request):
self.dj_request = dj_request
# 验证码长度
self.code_len = 4
# 验证码图片尺寸
self.img_width = 100
self.img_height = 30 # django中session的名称
self.session_key = 'verify_code' def gen_code(self):
""" 生成验证码 """
# 1. 使用随机数生成验证码字符串
code = self._get_vcode()
# 2. 把验证码存在的session
self.dj_request.session[self.session_key] = code
# 3. 准备随机元素(背景颜色、验证码文字的颜色、干扰线、)
font_color = ['black', 'darkblue', 'darkred', 'brown', 'green', 'darkmagenta', 'cyan', 'darkcyan']
# RGB随机背景色
bg_color = (random.randrange(230, 255), random.randrange(230, 255), random.randrange(230, 255))
# 字体路径
font_path = os.path.join(settings.BASE_DIR, 'medias', 'fonts', 'timesbi.ttf') # 创建图片
im = Image.new('RGB', (self.img_width, self.img_height), bg_color)
draw = ImageDraw.Draw(im) # 画干扰线
# 随机条数,到底画几条
for i in range(random.randrange(1, int(self.code_len / 2) + 1)):
# 线条的颜色
line_color = random.choice(font_color)
# 线条的位置
point = (
random.randrange(0, self.img_width * 0.2),
random.randrange(0, self.img_height),
random.randrange(self.img_width - self.img_width * 0.2, self.img_width),
random.randrange(0, self.img_height))
# 线条的宽度
width = random.randrange(1, 4)
draw.line(point, fill=line_color, width=width) # 画验证码
for index, char in enumerate(code):
code_color = random.choice(font_color)
# 指定字体
font_size = random.randrange(15, 25)
font = ImageFont.truetype(font_path, font_size)
point = (index * self.img_width / self.code_len,
random.randrange(0, self.img_height / 3))
draw.text(point, char, font=font, fill=code_color) buf = BytesIO()
im.save(buf, 'gif')
return HttpResponse(buf.getvalue(), 'image/gif') def _get_vcode(self):
random_str = 'ABCDEFGHIGKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789'
code_list = random.sample(list(random_str), self.code_len)
code = ''.join(code_list)
return code def validate_code(self, code):
""" 验证验证码是否正确 """
# 1. 转变大小写
code = str(code).lower()
vcode = self.dj_request.session.get(self.session_key, '')
# if vcode.lower() == code:
# return True
# return False
return vcode.lower() == code # if __name__ == '__main__':
# client = VerifyCode(None)
# client.gen_code()
verify
其他settings配置
# orm时间查询时候要是false
USE_TZ = False # 使用自定义模型的时候,当没有经过验证就会走这里
LOGIN_URL = '/weibo/user/login/' # CSRF 跨站请求伪造的另一个种解决方法,这样相当于植入到COOKIE中,模板通过jquery.cookie可以获取到
CSRF_USE_SESSIONS=False
文件备份脚本
import os
import os.path class FileBackup(object):
"""
文本文件备份
""" def __init__(self, src, dist):
"""
构造方法
:param src: 目录 需要备份的文件目录
:param dist: 目录 备份后的目录
"""
self.src = src
self.dist = dist def read_files(self):
"""
读取src目录下的所有文件
"""
ls = os.listdir(self.src)
print(ls)
for l in ls:
# 循环处理每一个文件/文件夹
# self.backup_file(l)
self.backup_file2(l) def backup_file(self, file_name):
"""
处理备份
:param file_name: 文件/文件夹的名称
"""
# 1. 判断dist是否存在,如果不存在,要创建这个目录
if not os.path.exists(self.dist):
os.makedirs(self.dist)
print('指定的目录不存在,创建完成') # 2. 判断文件是否为我们要备份的文件 # 拼接文件的完整路径
full_src_path = os.path.join(self.src, file_name)
full_dist_path = os.path.join(self.dist, file_name) # 首先要判断是否为文件夹,然后借助于文件的后缀名进行判断
if os.path.isfile(full_src_path) and os.path.splitext(full_src_path)[-1].lower() == '.txt':
print(full_src_path)
# 3. 读取文件内容
with open(full_dist_path, 'w', encoding='utf-8') as f_dist:
print('>> 开始备份【{0}】'.format(file_name))
with open(full_src_path, 'r', encoding='utf-8') as f_src:
while True:
rest = f_src.read(100)
if not rest:
break
# 4. 把读取到的内容写入到新的文件中
f_dist.write(rest)
f_dist.flush()
print('>>> 【{0}】备份完成'.format(file_name))
else:
print('文件类型不符合备份要求,跳过>>') def backup_file2(self, file_name):
"""
处理备份-优化版本
:param file_name: 文件/文件夹的名称
"""
# 1. 判断dist是否存在,如果不存在,要创建这个目录
if not os.path.exists(self.dist):
os.makedirs(self.dist)
print('指定的目录不存在,创建完成') # 2. 判断文件是否为我们要备份的文件 # 拼接文件的完整路径
full_src_path = os.path.join(self.src, file_name)
full_dist_path = os.path.join(self.dist, file_name) # 首先要判断是否为文件夹,然后借助于文件的后缀名进行判断
if os.path.isfile(full_src_path) and os.path.splitext(full_src_path)[-1].lower() == '.txt':
# 3. 读取文件内容
with open(full_dist_path, 'w', encoding='utf-8') as f_dist, \
open(full_src_path, 'r', encoding='utf-8') as f_src:
print('>> 开始备份【{0}】'.format(file_name))
while True:
rest = f_src.read(100)
if not rest:
break
# 4. 把读取到的内容写入到新的文件中
f_dist.write(rest)
f_dist.flush()
print('>>> 【{0}】备份完成'.format(file_name))
else:
print('文件类型不符合备份要求,跳过>>') if __name__ == '__main__':
# # 要备份的文件目录地址
# src_path = 'C:\\Users\\yima1\\Desktop\\py_learn\\chapter04\\src'
# # 备份后的目录地址
# dist_path = 'C:\\Users\\yima1\\Desktop\\py_learn\\chapter04\\dist' # 当前代码的目录名称
# C:\Users\yima1\Desktop\py_learn\chapter04\ test_backup.py
base_path = os.path.dirname(os.path.abspath(__file__))
# 要备份的文件目录地址
src_path = os.path.join(base_path, 'src')
print(src_path)
# 备份后的目录地址
dist_path = os.path.join(base_path, 'dist')
print(dist_path)
bak = FileBackup(src_path, dist_path)
bak.read_files() BACKUPFILE
慕课DJANGO配置的更多相关文章
- Windows下Apache+mod_python+Django配置
Windows下Apache+mod_python+Django配置 Apache 首先要安装Apache,我安装的版本是2.2.*: Python python肯定是要安装的,我安装的版本是2.5的 ...
- 【uWSGI】实战之Django配置经验
uWSGI 是应用服务器,实现了uwsgi, wsgi等协议,可以运行wsgi 应用 uwsgi 是协议名 Django配置 下面是自己经常用的一个配置模板,基于1.9以上的版本使用的, 主要基于dj ...
- 《玩转Django2.0》读书笔记-Django配置信息
<玩转Django2.0>读书笔记-Django配置信息 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 项目配置是根据实际开发需求从而对整个Web框架编写相应配置信息. ...
- Django配置后台xadmin管理界面
Django配置后台xadmin管理界面 python版本3.6.5 Django版本1.10.8(刚开始是2.1.5,由于各种错误,改成了低版本) 1.xadmin的安装,下载地址https://g ...
- Django 配置
Django 配置 运行 django-admin.py startproject [project-name] 命令会生成一系列文件,在Django 1.6版本以后的 settings.py 文 ...
- django配置静态文件
django配置静态文件 参考文章链接:http://blog.csdn.net/hireboy/article/details/8806098
- django配置静态文件的两种方法
方法一:按照django配置静态文件的方法,可以在APP应用目录下创建一个static的文件夹,然后在static文件夹下创建一个和APP同名的文件夹,如我有一个blog的django项目,在下面有一 ...
- DJango配置mysql数据库以及数据库迁移
DJango配置mysql数据库以及数据库迁移 一.Django 配置MySQL数据库 在settings.py中配置 import pymysql # 配置MySQL pymysql.install ...
- Django配置Mysql数据库 (Pycharm)
Django配置MySQL数据库方法 一.settings.py文件中修改数据库配置为下面的内容: # Database # https://docs.djangoproject.com/en/2.0 ...
- Django 配置MySQL数据库 mysql
Django 配置MySQL数据库 在settings.py中配置 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', # ...
随机推荐
- 9.prometheus监控--监控springboot2.x(Java)
一.环境部署 yum search java | grep jdk yum install -y java-11-openjdk-devel 二.监控java应用(tomcat/jar) JMX ex ...
- WebKit Inside: CSS 样式表的解析
CSS 全称为层叠样式表(Cascading Style Sheet),用来定义 HTML 文件最终显示的外观. 为了理解 CSS 的加载与解析,需要对 CSS 样式表的组成,尤其是 CSS Sele ...
- JS基础--JavaScript实例集锦(初学)
1.子节点childNodes: <!DOCTYPE html> <html> <head> <title>childNodes</title&g ...
- shape-outside
shape-outside定义一个由内容区域的外边缘封闭形成的形状 shape-outside 是一个非常实用的属性,可以实现一些比较复杂的文本环绕效果. shape-outside 的兼容性比较好, ...
- angular 16 路由守卫更新
在 angular16 中守卫使用方式进行了更新,route 守卫被弃用(取消了CanActivate的使用),新增了功能性守卫(CanActivateFn),支持 inject 注入,官网提供了一个 ...
- 运算符优先级 JAVA11
**运算符优先级 ** 规律:算术运算符优先级较高,关系和逻辑运算符优先级较低.多数运算符具有左结合性,单目运算符.三目运算符.赋值运算符具有右结合性. 运算符的优先级 举例 使用优先级为 1 的小括 ...
- JS / jQuery 刷新页面的方法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Vue——Ajax请求的基本使用
1.get方法发送Ajax请求 // 直接在 URL 上添加参数 ID=12345 axios.get('/user?ID=12345') .then(function (response) { co ...
- Base64编码解码 支持解码为 16进制
https://base64.xhlylx.com/
- Swift Lazy计算属性的线程安全分析
一.代码示例 // // ViewController.swift // LazyTest // // Created by lilun.ios on 2021/7/30. // import UIK ...