django-附件上传、media、extra、事务

1 普通上传

1.1 html

<form action="/index/" method="post" enctype="multipart/form-data">
    {% csrf_token %}
    <p><input type="text" name="user" id="user"></p>
    <p><input type="file" name="myFile" id="file"></p>
    <input type="submit">
</form>

1.2 views

def index(request):
    if request.method == "POST":
        print(request.POST)
        print(request.FILES)
        file_obj = request.FILES.get("myFile")
        print(file_obj.name)

        with open(file_obj.name,"wb") as f:
            for line in file_obj:
                f.write(line)

        return HttpResponse("上传成功。")
    return render(request, "index.html")

2 基于ajax实现

2.1 Html

<p><input type="file" name="myFile" id="file"></p>
{% csrf_token %}
<button>ajaxSend</button>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js "></script>
<script>
    $("button").click(function () {
        var formdata = new FormData();
        formdata.append("imgFile", $("#file")[0].files[0]);
        formdata.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val());
        $.ajax({
            url: "/upload_img/",
            type: "POST",
            data: formdata,
            processData: false,
            contentType: false,
            success: function (msg) {
                console.log(msg)
            }
        })
    })
</script>

2.2 views

import os,json
def upload_img(request):
    if request.is_ajax():
        obj = request.FILES.get("imgFile")
        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
        }
        return HttpResponse(json.dumps(data))

3 伪ajax上传

  基于FormData
  缺点:兼容性不好
  优点:Ajax直接发送
  伪Ajax,兼容性更好
    iframe,天生局部刷新
    form,天生整个页面刷新

3.1 html

<input type="text" placeholder="默认值看看刷新之后在不在" />
<form method="POST" target="uploadIframe" action="/upload_img2/" enctype="multipart/form-data">
    {% csrf_token %}
    <input type="text" name="user" />
    <a class="add-pub-btn pub-icons">
        上传
        <input type="file" name="avatar" id="imgUrl" />
    </a>
    <input type="submit" value="提交" />
</form>
<iframe id="ifm" name="uploadIframe" onload="successCallback(this);" style="display: none;" ></iframe>
<div id="imgList"></div>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js "></script>
<script>
    function successCallback(ths){
        var response = ths.contentWindow.document.body.innerHTML;
        response = JSON.parse(response);
        console.log(response);
        var img = document.createElement('img');
        img.src = "/" + response.data;

        $('#imgList').append(img);
    }
</script>

3.2 views

def upload2(request):
    return render(request,"iframe_upload.html")

def upload_img2(request):
    response = BaseResponse()
    try:
        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():
                for chunk in obj.chunks():
                    f.write(chunk)
    except Exception as e:
        response.msg = str(e)
    else:
        request.status = True
        response.data = img_path
    return HttpResponse(json.dumps(response.get_dict()))

4 上传按钮美化

4.1 css

<style>
    .add-pub-btn {
        width: 62px;
        height: 31px;
        line-height: 31px;
        display: block;
        text-align: center;
        color: #fff;
        font-size: 14px;
        font-weight: 700;
        margin-top: 5px;
        cursor: pointer;
    }
    .pub-icons {
        background: url(/static/img/bottom.png?v=2.8) no-repeat 0 0;
    }
    #imgUrl {
        border: 0;
        filter: alpha(opacity=0);
        background: 0 0;
        opacity: 0;
        -moz-opacity: 0;
        width: 62px;
        height: 31px;
        left: 5px;
        top: 5px\9;
        position: absolute;
        cursor: pointer;
    }
</style>

4.2 按钮设置

<a class="add-pub-btn pub-icons">
    上传
    <input type="file" name="avatar" id="imgUrl" />
</a>

5 图片预览

本图片的预览功能,主要利用html.js的FileReader进行实现的

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册</title>
    <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"
          integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <style>
        #avatar {
            margin-top: 5px;
            margin-bottom: 5px;
            position: relative;
            width: 100px;
            height: 100px;
        }

        #avatar_img, #file {
            width: 100px;
            height: 100px;
            position: absolute;
            left: 15px;
            top: 0;
        }

        #file {
            opacity: 0;
        }
    </style>
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-8" id="avatar">
            <img src="default.png" class="img-thumbnail" id="avatar_img">
            <input type="file" id="file">
        </div>
    </div>
</div>

<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js "></script>
<script type="text/javascript">
    // 预览功能
    $("#file").change(function () {
        var choose_file = $("#file")[0].files[0];
        var reader = new FileReader();
        reader.readAsDataURL(choose_file);
        reader.onload = function () {
            $("#avatar_img").attr("src", this.result)
        }
    });
</script>

</body>
</html>

6 文件上传路径

6.1 配置
在settings中配置

MEDIA_ROOT=os.path.join(BASE_DIR,"blog","media")
MEDIA_URL="/media/"

在urls.py中配置

from django.views.static import serve

url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),

6.2 使用

<img src='/media/avatarDir/a.png'>

7 extra

  有些情况下,Django的查询语法难以简单的表达复杂的 WHERE 子句,对于这种情况, Django 提供了 extra() QuerySet修改机制 — 它能在 QuerySet生成的SQL从句中注入新子句
extra可以指定一个或多个 参数,例如 select, where or tables. 这些参数都不是必须的,但是你至少要使用一个!要注意这些额外的方式对不同的数据库引擎可能存在移植性问题.(因为你在显式的书写SQL语句),除非万不得已,尽量避免这样做

# in sqlite:
    article_obj=models.Article.objects
              .filter(nid=1)
              .extra(select={"standard_time":"strftime('%%Y-%%m-%%d',create_time)"})
              .values("standard_time","nid","title")
    print(article_obj)
    # <QuerySet [{'title': 'MongoDb 入门教程', 'standard_time': '2017-09-03', 'nid': 1}]>
current_user = models.UserInfo.objects.filter(username=username).first()   #当前用户
【每一步的分析过程】
1、models.Article.objects.all()  #查出每一篇文章
2、models.Article.objects.all().filter(user=current_user)  #查出当前用户的所有文章
3、models.Article.objects.all().filter(user=current_user).extra(select={"filter_create_date":"strftime('%%Y/%%m',create_time)"}).values_list("filter_create_date")
#查出当前用户的所有文章的create_time,并且只取出年份和月份
解决方案:使用extra方法 
extra使用来进行过滤的,参数select必须等于一个字典(转成sql的where语句去执行,查出create_time,然后转换成自己格式化的时间)
4、models.Article.objects.all().filter(user=current_user).extra(select={"filter_create_date":"strftime('%%Y/%%m',create_time)"}).values_list("filter_create_date").annotate(Count("title"))
#按照查询出来的年份和月份进行分组,并且显示文章个数

8 事务使用

from django.contrib.auth import authenticate
with transaction.atomic():
    models.ArticleUpDown.objects.create(user_id=user_id, article_id=article_id)
    models.Article.objects.filter(nid=article_id).update(up_count=F("up_count") + 1)

 

posted @ 2017-12-13 16:05  平凡执着  阅读(251)  评论(0编辑  收藏  举报