1,ModelForm
Model + Form => 验证 + 数据库操作
- class LoginModelForm(xxx):
利用model.A 中的字段
1,生成HTML标签:class Meta:...
2,mf = xxxModelForm(instance=ModelObj
3,额外的标签 is_rmb = Ffields.CharField(widget=Fwidgets.CheckboxInput())
4,各种验证 is_valid() -> 各种钩子。。。
5,mf.save()
等价于
instance = mf.save(False)
instance.save()
mf.save_m2m()
在命名上有一些耦合,所以需要的话更改一下名字
比如:
from django.forms import fields as Ffields
from django.forms import widgets as Fwidgets
Django 之ModelForm 组件
ModelForm
a. class Meta:
model, # 对应Model的
fields=None, # 字段
exclude=None, # 排除字段
labels=None, # 提示信息
help_texts=None, # 帮助提示信息
widgets=None, # 自定义插件
error_messages=None, # 自定义错误信息(整体错误信息from django.core.exceptions import NON_FIELD_ERRORS)
field_classes=None # 自定义字段类 (也可以自定义字段)
localized_fields=('birth_date',) # 本地化,如:根据不同时区显示数据
如:
数据库中
2016-12-27 04:10:57
setting中的配置
TIME_ZONE = 'Asia/Shanghai'
USE_TZ = True
则显示:
2016-12-27 12:10:57
b. 验证执行过程
is_valid -> full_clean -> 钩子 -> 整体错误
c. 字典字段验证
def clean_字段名(self):
# 可以抛出异常
# from django.core.exceptions import ValidationError
return "新值"
d. 用于验证
model_form_obj = XXOOModelForm()
model_form_obj.is_valid()
model_form_obj.errors.as_json()
model_form_obj.clean()
model_form_obj.cleaned_data
e. 用于创建
model_form_obj = XXOOModelForm(request.POST)
#### 页面显示,并提交 #####
# 默认保存多对多
obj = form.save(commit=True)
# 不做任何操作,内部定义 save_m2m(用于保存多对多)
obj = form.save(commit=False)
obj.save() # 保存单表信息
obj.save_m2m() # 保存关联多对多信息
f. 用于更新和初始化
obj = model.tb.objects.get(id=1)
model_form_obj = XXOOModelForm(request.POST,instance=obj)
...
PS: 单纯初始化
model_form_obj = XXOOModelForm(initial={...})
实例:
from django.shortcuts import render,HttpResponse
from app01 import models
from django import forms
#防止引用方法名 被覆盖,所以换一下名字
from django.forms import fields as Ffields
from django.forms import widgets as Fwidgets
class UserInfoModelForm(forms.ModelForm):
is_rmb = Ffields.CharField(
widget=Fwidgets.CheckboxInput()
)
class Meta:
model = models.UserInfo
fields = '__all__'
# fields = ['username','email']
# exclude = ['username']
#提示信息
labels = {
'username':'用户名',
'email' :'邮箱',
}
#帮助提示信息
help_texts = {
'username':'...'
}
#插件
widgets = {
'username':Fwidgets.Textarea(attrs={'class':'c1'})
}
#自定义错误信息
error_messages={
'__all__':{
},
'email':{
'required':'邮箱不能为空',
'invalid':'邮箱格式错误',
}
}
#自定义字段,改变格式,比如邮箱格式改变为URL格式
field_classes = {
# 'email':Ffields.URLField
}
# localized_fields=('ctime')
#还需要在setting 中配置
def clean_username(self):
old = self.cleaned_data['username']
return old
class UserInfoForm(forms.Form):
username = Ffields.CharField(max_length=32)
email = Ffields.EmailField()
user_type = Ffields.ChoiceField(
choices=models.UserType.objects.values_list('id','caption')
)
def __int__(self,*args,**kwargs):
super(UserInfoForm,self).__init__(*args,**kwargs)
self.fields['user_type'].choices = models.UserType.objects.values_list('id','caption')
def index(request):
if request.method == "GET":
obj = UserInfoModelForm()
return render(request,'index.html',{'obj':obj})
elif request.method == "POST":
obj = UserInfoModelForm(request.POST)
# print(obj.is_valid())
# print(obj.cleaned_data)
# print(obj.errors)
if obj.is_valid():
obj.save()
#一句顶三句,哈哈
# instance = obj.save(False)
# instance.save()
# obj.save_m2m()
return render(request,'index.html',{'obj':obj})
def user_list(request):
li = models.UserInfo.objects.all().select_related('user_type')
return render(request,'user_list.html',{'li':li})
def user_edit(request,nid):
#获取当前id 对象的用户信息
#显示用户已经存在数据
if request.method == "GET":
user_obj = models.UserInfo.objects.filter(id=nid).first()
mf = UserInfoModelForm(instance=user_obj)
return render(request,'user_edit.html',{'mf':mf,'nid':nid})
elif request.method =="POST":
user_obj = models.UserInfo.objects.filter(id=nid).first()
mf = UserInfoModelForm(request.POST,instance=user_obj)
if mf.is_valid():
mf.save()
else:
print(mf.errors.as_json())
return render(request,'user_edit.html',{'mf':mf,'nid':nid})
2,Ajax
参考博客 https://www.cnblogs.com/wupeiqi/articles/5703697.html
原生AJAX
Ajax主要就是使用 【XmlHttpRequest】对象来完成请求的操作,该对象在主流浏览器中均存在(除早起的IE),
Ajax首次出现IE5.5中存在(ActiveX控件)
1,XXMLHttpRequest 对象介绍
XMLHttpRequest 对象的主要方法:
a. void open(String method,String url,Boolen async)
用于创建请求
参数:
method: 请求方式(字符串类型),如:POST、GET、DELETE...
url: 要请求的地址(字符串类型)
async: 是否异步(布尔类型)
b. void send(String body)
用于发送请求
参数:
body: 要发送的数据(字符串类型)
c. void setRequestHeader(String header,String value)
用于设置请求头
参数:
header: 请求头的key(字符串类型)
vlaue: 请求头的value(字符串类型)
d. String getAllResponseHeaders()
获取所有响应头
返回值:
响应头数据(字符串类型)
e. String getResponseHeader(String header)
获取响应头中指定header的值
参数:
header: 响应头的key(字符串类型)
返回值:
响应头中指定的header对应的值
f. void abort()
终止请求
XMLHttpRequest对象的主要属性
a. Number readyState
状态值(整数)
详细:
0-未初始化,尚未调用open()方法;
1-启动,调用了open()方法,未调用send()方法;
2-发送,已经调用了send()方法,未接收到响应;
3-接收,已经接收到部分响应数据;
4-完成,已经接收到全部响应数据;
b. Function onreadystatechange
当readyState的值改变时自动触发执行其对应的函数(回调函数)
c. String responseText
服务器返回的数据(字符串类型)
d. XmlDocument responseXML
服务器返回的数据(Xml对象)
e. Number states
状态码(整数),如:200、404...
f. String statesText
状态文本(字符串),如:OK、NotFound...
jquery
伪Ajax操作
选择的时机
如果发送的是普通数据 -> jQuery,XMLHttpRequest,iframe
实例:
ajax.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ajaxtitle>
head>
<body>
{#{% csrf_token %}#}
<input type="text">
<input type="button" value="Ajax1" onclick="Ajax1();">
{#伪造 AJAX 请求#}
<form action="/ajax_json/" method="post" target="ifm1">
<iframe name="ifm1" frameborder="0">iframe>
<input type="text" name="username">
<input type="text" name="email">
<input type="submit" onclick="sumbitForm();" value="Form提交">
form>
<script type="text/javascript" src="/static/jquery-3.4.1.js">script>
<script>
function getXHR() {
var xhr = null;
if(XMLHttpRequest){
xhr = new XMLHttpRequest();
}
else{
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
return xhr;
}
function Ajax1() {
var xhr = new XMLHttpRequest();
//指定连接方式和地址---文件方式
xhr.open('POST','/ajax_json/',true);
// 定义回调函数
xhr.onreadystatechange = function () {
if(xhr.readyState == 4){
//接受完毕
var obj = JSON.parse(xhr.responseText);
console.log(obj);
}
};
xhr.setRequestHeader('k1','v1');
// 设置请求头
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded;charset-UTF-8');
// 发送请求
xhr.send("name=root;pwd=123");
}
<!-- 获取输入值 并放在iframe 的src 中去搜索
function iframeRequest() {
var url = $('#url').val();
$("#ifm").attr('src',url);
}
-->
function sumbitForm() {
$('#ifm1').load(function () {
var text = $('#ifm1').contents().find('body').text();
var obj = JSON.parse(text);
})
}
script>
body>
html>
views.py
def ajax(request):
return render(request,'ajax.html')
def ajax_json(request):
ret = {'code':True,'data':None}
import json
# return HttpResponse(json.dumps(ret),status=404,reason='Not Found')
return HttpResponse(json.dumps(ret))
3,文件上传(包含预览)
Form 提交
Ajax 上传文件
时机:
如果发送的是文件, -> iframe,jQuery(FormData),XMLHttpRequest(FormData)
实例:
upload.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title>
<style>
.upload{
display: inline-block;padding: 10px;
background-color: brown;
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
z-index: 90;
}
.file{
width: 100px;height: 50px;opacity: 0;
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
z-index: 100;
}
style>
head>
<body>
{#给上传按钮 加上一层新的样式,用遮盖加隐藏的方法#}
<div style="position: relative;width: 100px;height: 50px;">
<input class="file" type="file" id="fafafa" name="afafaf" />
<a class="upload">上传a>
div>
<input type="button" value="提交XHR" onclick="xhrSubmit();" />
<input type="button" value="提交jQuery" onclick="jqSubmit();" />
{# <hr/>#}
<form id="form1" action="/upload_file/" method="POST" enctype="multipart/form-data" target="ifm1">
<iframe id="ifm1" name="ifm1" style="display: none;">iframe>
<input type="file" name="fafafa" onchange="changeUpalod();" />
{# <input type="submit" onclick="iframeSubmit();" value="Form提交"/>#}
form>
<div id="preview">div>
<script src="/static/jquery-3.4.1.js">script>
<script>
{#预览#}
function changeUpalod(){
$('#ifm1').load(function(){
var text = $('#ifm1').contents().find('body').text();
var obj = JSON.parse(text);
$('#preview').empty();
var imgTag = document.createElement('img');
imgTag.src = "/" + obj.data;
$('#preview').append(imgTag);
});
$('#form1').submit();
}
<!-- jquery 方式进行文件提交 -->
function jqSubmit(){
// $('#fafafa')[0]
var file_obj = document.getElementById('fafafa').files[0];
var fd = new FormData();
fd.append('username','root');
fd.append('fafafa',file_obj);
$.ajax({
url: '/upload_file/',
type: 'POST',
data: fd,
processData: false, // tell jQuery not to process the data
contentType: false, // tell jQuery not to set contentType
success:function(arg,a1,a2){
console.log(arg);
console.log(a1);
console.log(a2);
}
})
}
<!-- XMLHttpRequest 方式进行文件提交 -->
function xhrSubmit(){
// $('#fafafa')[0]
var file_obj = document.getElementById('fafafa').files[0];
var fd = new FormData();
fd.append('username','root');
fd.append('fafafa',file_obj);
var xhr = new XMLHttpRequest();
xhr.open('POST', '/upload_file/',true);
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
// 接收完毕
var obj = JSON.parse(xhr.responseText);
console.log(obj);
}
};
xhr.send(fd);
}
{#iframe 方式进行文件提交#}
function iframeSubmit(){
$('#ifm1').load(function(){
var text = $('#ifm1').contents().find('body').text();
var obj = JSON.parse(text);
$('#preview').empty();
var imgTag = document.createElement('img');
imgTag.src = "/" + obj.data;
$('#preview').append(imgTag);
})
}
script>
body>
html>
views.py
def upload(request)
def upload(request):
return render(request,'upload.html')
def upload_file(request)
def upload_file(request):
username = request.POST.get('username')
fafafa = request.FILES.get("fafafa")
import os
img_path = os.path.join('static/imgs/',fafafa.name)
with open(img_path,'wb') as f:
for item in fafafa.chunks():
f.write(item)
ret = {'code':True,'data':img_path}
import json
return HttpResponse(json.dumps(ret))
4,图片验证码+Session
session
check_code.py(依赖:Pillow,字体文件)
src 属性后面加 ?
实例:
login.html
<html>
<head lang="en">
<meta charset="UTF-8">
<title>title>
<link rel="stylesheet" href="/static/plugins/bootstrap/css/bootstrap.css"/>
<link rel="stylesheet" href="/static/plugins/font-awesome/css/font-awesome.css"/>
<link rel="stylesheet" href="/static/css/edmure.css"/>
<link rel="stylesheet" href="/static/css/commons.css"/>
<link rel="stylesheet" href="/static/css/account.css"/>
<style>
style>
head>
<body>
<div class="login">
<div style="font-size: 25px; font-weight: bold;text-align: center;">
用户登陆
div>
<form role="form" action="/login.html" method="POST">
{% csrf_token %}
<div class="form-group">
<label for="username">用户名label>
<input type="text" class="form-control" placeholder="请输入用户名">
div>
<div class="form-group">
<label for="password">密码label>
<input type="password" class="form-control" placeholder="请输入密码">
div>
<div class="form-group">
<label for="password">验证码label>
<div class="row">
<div class="col-xs-7">
<input type="text" class="form-control" placeholder="请输入验证码" name="check_code">
div>
<div class="col-xs-5">
<img src="/check_code.html" onclick="changeCheckCode(this);">
div>
div>
div>
<div class="checkbox">
<label>
<input type="checkbox"> 一个月内自动登陆
label>
<div class="right">
<a href="#">忘记密码?a>
div>
div>
<button type="submit" class="btn btn-default">登 陆button>
form>
div>
<script>
function changeCheckCode(ths){
ths.src = ths.src + '?';
}
script>
body>
html>
views.py
def check_code(request):
"""
验证码
:param request:
:return:
"""
# stream = BytesIO()
# img, code = create_validate_code()
# img.save(stream, 'PNG')
# request.session['CheckCode'] = code
# return HttpResponse(stream.getvalue())
# data = open('static/imgs/avatar/20130809170025.png','rb').read()
# return HttpResponse(data)
# 1. 创建一张图片 pip3 install Pillow
# 2. 在图片中写入随机字符串
# obj = object()
# 3. 将图片写入到制定文件
# 4. 打开制定目录文件,读取内容
# 5. HttpResponse(data)
stream = BytesIO()
img, code = create_validate_code()
img.save(stream,'PNG')
request.session['CheckCode'] = code
return HttpResponse(stream.getvalue())
def login(request):
"""
登陆
:param request:
:return:
"""
# if request.method == "POST":
# if request.session['CheckCode'].upper() == request.POST.get('check_code').upper():
# pass
# else:
# print('验证码错误')
if request.method == 'POST':
code = request.POST.get('check_code')
if code.upper() == request.session['CheckCode'].upper():
print('验证码正确')
else:
print('验证码错误')
return render(request, 'login.html')
5,CKEditor,UEEditor,TinyEditor,KindEditor()*
基本使用
文件上传,多文件上传,文件空间管理
XSS 攻击(过滤的函数或类)
kindeditor 下载地址
HTML在线编辑器官方参考文档
实例:
kind.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title>
head>
<body>
<form>
{% csrf_token %}
<div style="width: 500px;margin: 0 auto">
<textarea id="content">textarea>
div>
<input type="submit" value="提交"/>
form>
<script src="/static/jquery-1.12.4.js">script>
<script src="/static/kindeditor-4.1.10/kindeditor-all.js">script>
<script>
$(function () {
KindEditor.create('#content', {
{# items: ['superscript', 'clearhtml', 'quickformat', 'selectall']#}
{# noDisableItems: ["source", "fullscreen"],#}
{# designMode: false#}
uploadJson: '/upload_img/',
fileManagerJson: '/file_manager/',
allowImageRemote: true,
allowImageUpload: true,
allowFileManager: true,
extraFileUploadParams: {
csrfmiddlewaretoken: "{{ csrf_token }}"
},
filePostName: 'fafafa'
});
})
script>
body>
html>
views.py
def kind(request):
return render(request, 'kind.html')
def upload_img(request):
request.GET.get('dir')
print(request.FILES.get('fafafa'))
# 获取文件保存
import json
dic = {
'error': 0,
'url': '/static/imgs/20130809170025.png',
'message': '错误了...'
}
return HttpResponse(json.dumps(dic))
import os
import time
import json
def file_manager(request):
"""
文件管理
:param request:
:return:
{
moveup_dir_path:
current_dir_path:
current_url:
file_list: [
{
'is_dir': True,
'has_file': True,
'filesize': 0,
'dir_path': '',
'is_photo': False,
'filetype': '',
'filename': xxx.png,
'datetime': time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(os.path.getctime(abs_item_path)))
},
{
'is_dir': True,
'has_file': True,
'filesize': 0,
'dir_path': '',
'is_photo': False,
'filetype': '',
'filename': xxx.png,
'datetime': time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(os.path.getctime(abs_item_path)))
}
]
}
"""
dic = {}
root_path = 'C:/Users/Administrator/PycharmProjects/day24/static/'
static_root_path = '/static/'
request_path = request.GET.get('path')
if request_path:
abs_current_dir_path = os.path.join(root_path, request_path)
move_up_dir_path = os.path.dirname(request_path.rstrip('/'))
dic['moveup_dir_path'] = move_up_dir_path + '/' if move_up_dir_path else move_up_dir_path
else:
abs_current_dir_path = root_path
dic['moveup_dir_path'] = ''
dic['current_dir_path'] = request_path
dic['current_url'] = os.path.join(static_root_path, request_path)
file_list = []
for item in os.listdir(abs_current_dir_path):
abs_item_path = os.path.join(abs_current_dir_path, item)
a, exts = os.path.splitext(item)
is_dir = os.path.isdir(abs_item_path)
if is_dir:
temp = {
'is_dir': True,
'has_file': True,
'filesize': 0,
'dir_path': '',
'is_photo': False,
'filetype': '',
'filename': item,
'datetime': time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(os.path.getctime(abs_item_path)))
}
else:
temp = {
'is_dir': False,
'has_file': False,
'filesize': os.stat(abs_item_path).st_size,
'dir_path': '',
'is_photo': True if exts.lower() in ['.jpg', '.png', '.jpeg'] else False,
'filetype': exts.lower().strip('.'),
'filename': item,
'datetime': time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(os.path.getctime(abs_item_path)))
}
file_list.append(temp)
dic['file_list'] = file_list
return HttpResponse(json.dumps(dic))