django 文件上传和菜单分级,mysql支持事务,F模块自增字段, python发送get,post请求

2023-04-04,,

一、文件上传
方法一

上传文件视图函数
def upload_img(request):
    obj = request.FILES.get('file')    #前端js设置的key

    img_path = os.path.join('static','img',obj.name)

    with open(img_path,mode='wb') as f:
        for chunk in obj.chunks():
            f.write(chunk)
    data = {
        'status': True,
        'path': img_path
    }
    import json
    return HttpResponse(json.dumps(data))
    
    
前端页面
form表单
            <form>
                  <div class="form-group">
                    <label for="exampleInputFile">上传图片</label>
                    <input type="file" id="exampleInputFile">
                      <button type="button" class="btn btn-default" id="uploadfile">上传</button>
{#                    <p class="help-block">Example block-level help text here.</p>#}
                  </div>

                  <div class="form-group">
                      <label for="select_news">选择新闻类型</label>
                      <select class="form-control" id="select_news">
                          <option>42区</option>
                          <option>段子</option>
                          <option>图片</option>
                          <option>挨踢1024</option>
                          <option>你问我答</option>
                      </select>
                  </div>
                  <div class="form-group">
                    <label for="news_url">新闻链接</label>
                    <input type="text" class="form-control" id="news_url" placeholder="Url">
                  </div>

                  <div class="form-group">
                    <label for="news_title">新闻标题</label>
                    <textarea class="form-control" rows="3" id="news_title"></textarea>
                  </div>

                  <div class="form-group">
                    <label for="news_summary">新闻简介</label>
                    <textarea class="form-control" rows="3" id="news_summary"></textarea>
                  </div>

                  <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
                    <button type="button" class="btn btn-primary" id="news_publish">提交</button>
                  </div>
              </form>
              

js 通过FormData方法处理
$(document).ready(function () {
    $('#uploadfile').click(function () {
        var formData = new FormData();
        formData.append('file',$('#exampleInputFile')[0].files[0]);
        $.ajax({
            url: '/upload',
            type: 'POST',
            data: formData,
            processData: false, //添加这两个参数,表示将原生文件发到后台
            contentType: false,
            success: function (res) {
                console.log(res);
            }
        })
    })
});



方法二

前端页面用form和iframe组合伪造ajax提交
<form method="POST" target="xxxxxx" action="/upload_img2/" enctype="multipart/form-data">
        {% csrf_token %}
        <input type="text" name="user" />
        <a >
            上传
            <input type="file" name="avatar"  />
        </a>
        <input type="submit" value="提交" />
</form>
<iframe id="ifm" name="xxxxxx" onload="successCallback(this);"  ></iframe>

注: form属性target的值必须和iframe的name属性值一样


view视图函数处理上传请求
def upload_img2(request):
    response = BaseResponse()
    try:
        user = request.POST.get('user')    #处理post请求
        obj = request.FILES.get('avatar')    #处理上传文件
        img_path = os.path.join('static', 'img', obj.name)
        with open(img_path,mode='wb') as f:
            for chunk in obj.chunks():
                f.write(chunk)
    except Exception as e:
        response.msg = str(e)
    else:
        response.status = True
        response.data = img_path
    return HttpResponse(json.dumps(response.get_dict()))
    


二、django对mysql事务的支持
view视图

import json
from django.db.models import F    # F模块实现数据库字段自增
from django.db import transaction    #支持事务原子性,对数据库的连续操作,操作成功必须每个sql都成功,否则都失败
from utils.response import LikeResponse

def do_like(request):
    """
    点赞
    :param request:
    :return:
    """
    response = LikeResponse()
    try:
        new_id = request.POST.get('newId')
        # 当前登录用户ID
        # uid = request.session.get('uid')
        uid = 1

        exist_like = models.Like.objects.filter(nnew_id=new_id,uuser_id=uid).count()
        with transaction.atomic():    #事务
            if exist_like:
                models.Like.objects.filter(nnew_id=new_id, uuser_id=uid).delete()
                models.News.objects.filter(id=new_id).update(like_count=F('like_count') - 1)
                response.code = 666
            else:
                models.Like.objects.create(nnew_id=new_id,uuser_id=uid)
                models.News.objects.filter(id=new_id).update(like_count=F('like_count') + 1)
                response.code = 999
    except Exception as e:
        response.msg = str(e)
    else:
        response.status = True
    return HttpResponse(json.dumps(response.get_dict()))
    
    
  三、多级菜单,多级评论
  
view视图
from django.shortcuts import render, HttpResponse, redirect

# Create your views here.
import json
from django.db.models import F
from app01 import models
from django.db import transaction
from utils.response import LikeResponse

def comment_list(request):
    li = [
        {'id': 1, 'user': '银秋良', 'content': '灌我鸟事', 'parent_id': None},
        {'id': 2, 'user': '银秋良', 'content': '管我鸟事', 'parent_id': None},
        {'id': 3, 'user': '型谱', 'content': '你个文盲', 'parent_id': 1},
        {'id': 4, 'user': '详解', 'content': '好羡慕你们这些没脸的人呀', 'parent_id': 2},
        {'id': 5, 'user': '银秋良', 'content': '你是流氓', 'parent_id': 3},
        {'id': 6, 'user': '银秋良', 'content': '你冷库无情', 'parent_id': 5},
        {'id': 7, 'user': '银秋良', 'content': '你才冷酷无情', 'parent_id': 4},
        {'id': 8, 'user': '银秋良', 'content': '你无理取闹', 'parent_id': 4},
    ]

    com_list = build_comment_data(li)
    html = build_comment_tree(com_list)

    return render(request, 'comment_list.html', {'comment_html': html})
 
 #将列表子元素放入父级元素中   
def build_comment_data(li):
    dic = {}
    for item in li:
        item['children'] = []
        dic[item['id']] = item

    result = []
    for item in li:
        pid = item['parent_id']
        if pid:
            dic[pid]['children'].append(item)
        else:
            result.append(item)
    return result

#生成 html页面
def build_comment_tree(com_list):
    tpl = """
    <div class='item'>
        <div class='title'>{0}:{1}</div>
        <div class='body'>{2}</div>
    </div>
    """

    html = ""
    for item in com_list:
        if not item['children']:
            html += tpl.format(item['user'],item['content'],"")
        else:
            html += tpl.format(item['user'], item['content'], build_comment_tree(item['children']))
    return html
    
comment_list.html页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .body{
            margin-left: 30px;
        }
        .hide{
            display: none;
        }

    </style>
</head>
<body>
    <h2>评论</h2>
    {{ comment_html|safe }}

    <h2>菜单</h2>
    <hr/>
    <script src="/static/jquery-3.1.1.js"></script>
    <script>
        $(function () {
            $('.title').click(function () {
                if ($(this).next().hasClass('hide')){
                    $(this).next().removeClass('hide');
                }else{
                    $(this).next().addClass('hide');
                }
            })
        })
    </script>

</body>
</html>

四、python实现get和post请求
客户端:
import requests
response = requests.get('

传递字典类型参数
data_dict = {
'k1':'v1',
'k2':'v2'
}
content-type: application/x-www-form-urlencoded 
response = requests.post('
 print(response.text)
 
传递json类型参数
content-type: appcation/json
response = requests.post('
 print(response.text)
 
 
 服务端Django:
 from django.views.decorators.csrf import csrf_exempt,csrf_protect
 @csrf_exempt
 def asset(request):
 if request.method == "GET":
     return HttpResponse('收到:GET')
 else:
     print(request.POST)
     print(request.body)
 return HttpResponse('收到:POST')