python Django ModelForm,Ajax,文件上传,图片验证码+Session,HTML在线编辑器

Django ModelForm,Ajax,文件上传,图片验证码+Session,HTML在线编辑器

  1. ModelForm
  2. Ajax
  3. 文件上传
  4. 图片验证码+Session
  5. HTML在线编辑器

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在线编辑器官方参考文档
python Django ModelForm,Ajax,文件上传,图片验证码+Session,HTML在线编辑器_第1张图片
实例:

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))

你可能感兴趣的:(python)