Django project actual user avatar upload and access

 

 

1 Save the file to the server locally

upload.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">

</head>
<body>

<form action="" method="post" enctype="multipart/form-data">
    {% csrf_token %}
    <div>用户名:<input type="text" name="username"></div>
    <div>头像<input type="file" name="avatar"></div>
    <input type="submit" value="提交">
</form>

</body>
</html>

urls.py

from django.conf.urls import url
from app01 import views

urlpatterns = [
    url(r'^upload',views.upload)
]

views.py

from django.shortcuts import render,HttpResponse

def upload(request):
    if request.method == 'POST':
        name = request.POST.get('username')
        avatar = request.FILES.get('avatar')

        with open(avatar.name,'wb') as f:
            for line in avatar:
                f.write(line)
        return HttpResponse('ok')

    return render(request,'upload.html')

Summarize

In this way, we have done a small example of basic file uploading. There are a few points to note here:

  1. csrf_token verification needs to be added to the form form
  2. The type value of the input box of the file is file
  3. To get the file in the view function, use the request.FILES.get() method
  4. The name of the file can be obtained through obj.name

2 Upload the file to the database

models.py

from django.db import models


class User(models.Model):
    username = models.CharField(max_length=16)
    avatar = models.FileField(upload_to='avatar')

views.py

def upload(request):
    if request.method == 'POST':
        name = request.POST.get('username')
        avatar = request.FILES.get('avatar')

        models.User.objects.create(username=name,avatar=avatar)
        return HttpResponse('ok')

    return render(request,'upload.html')

Summarize

The function of uploading files to the database has been implemented above. There are a few points to note:

  1. The so-called uploading to the database does not mean that the image itself or the binary code is placed in the database. In fact, it is also uploading the file to the local server. The database only stores the path of a file, so that when the user wants to call the file, he can go to the specified server through the path. location found
  2. When creating an ORM, the avatar field must have an attribute of upload_to='', specifying where the uploaded file is placed
  3. When adding to the database, the file field attribute assignment is the same in form as the ordinary field, such as: models.User.objects.create(username=name,avatar=avatar)
  4. If there are duplicate file names uploaded by two users, the system will automatically rename the file, and the effect is as follows:

additional

We have implemented the function. It seems that when we call the file, we only need to access the picture through the file itself that has been saved in the database file path, so that it appears on the web page. In fact, this is not the case.

We need to configure something so that django can find it, otherwise it will not pass the urls verification, and the reason why we can directly access the static files in static is because django has already configured it for us.

 

The configuration steps are as follows:

1. Configure in the site's setting.py

MEDIA_ROOT=os.path.join(BASE_DIR,"blog","media") #blog is the project name, media is the conventional folder name
 MEDIA_URL="/media/" # Similar to STATIC_URL, specifies that users can find files through this path

2. Configure in urls.py

from django.views.static import serve
from upload import settings #upload is the site name

url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
After configuration, you can access the picture through http://127.0.0.1:8001/media/milk.png

 

 3 Submit files with AJAX

upload.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>

<form>
    {% csrf_token %}
    <div>用户名:<input id="name-input" type="text"></div>
    <div>头像<input id="avatar-input" type="file"></div>
    <input id="submit-btn" type="button" value="提交">
</form>

<script src="/static/js/jquery-3.2.1.min.js"></script>
<script>
    $('#submit-btn').on('click',function () {
        formdata = new FormData();
        formdata.append('username',$('#name-input').val());

formdata.append("avatar",$("#avatar")[0].files[0]);
       formdata.append("csrfmiddlewaretoken",$("[name='csrfmiddlewaretoken']").val()); 
$.ajax({
processData:false,
contentType:false,
url:'/upload',
type:'post',
data:formdata,
success:function (arg) {
if (arg.state == 1){ alert('成功!') }else { alert('失败!') } } }) });
</script> </body> </html>

views.py

from django.shortcuts import render,HttpResponse
from django.http import JsonResponse
from app01 import models

def upload(request):
    if request.method == 'POST':
        name = request.POST.get('username')
        avatar = request.FILES.get('avatar')

        try:
            models.User.objects.create(username=name,avatar=avatar)
            data = {'state':1}
        except:
            data = {'state':0}

        return JsonResponse(data)

    return render(request,'upload.html')

Summarize

  1. When Ajax uploads, the tpye of the button must not use submit
  2. When Ajax uploads, the value of the data parameter is no longer a common 'dictionary' type value, but a FormData object
    • Create object formdata = new FormData();
    • Add the value formdata.append('username',$('#name-input').val());
  3. Ajax should add csrf verification when doing post submission
    • formdata.append("csrfmiddlewaretoken",$("[name='csrfmiddlewaretoken']").val());
  4. Finally, there are two parameter settings when Ajax uploads files
    • processData:false
    • contentType:false

4 There is a preview function when uploading image files

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>

<form>
    <!----Use a label tag to bind the upload file input box to the image,
          Clicking on the picture is equivalent to clicking the button to upload the file ---->
    <label><img id="avatar-img" src="/static/img/default.png" width="80px" height="80px">
        <div>头像<input id="avatar-input" hidden type="file"></div>
    </label>

    <input id="submit-btn" type="button" value="提交">
</form>

<script src="/static/js/jquery-3.2.1.min.js"></script>

<script>

    // Upload file button (image in label) click event
    $('#avatar-input').on('change',function () {
        // Get the last image selected by the user
        var choose_file=$(this)[0].files[0];
        // Create a new FileReader object to read file information
        var reader=new FileReader();
        // Read the path of the image uploaded by the user
        reader.readAsDataURL(choose_file);
        // After reading, modify the src attribute of the image to the local path of the image uploaded by the user
        reader.onload=function () {
             $("#avatar-img").attr("src",reader.result)
        }
    });

</script>

 5 Summary

For file upload, whether it is a direct form submission or Ajax submission, the fundamental problem is to tell the browser that you are uploading a file instead of a normal string

And how to tell the browser, that is, through the ContentType parameter of the request weight, we don't need to specify it when uploading a normal string, because it has a default value,

And if you want to upload files, you need to specify it separately. Summarize the following points

  1. If the form is uploaded, the  ContentType is specified by enctype="multipart/form-data" 
  2. For ajax upload, specify ContentType through   processData:false and contentType:false
  3. When the form is uploaded, the file data is ''wrapped'' data through the <input type="file"> tag,
  4. When ajax is uploaded, data is added through a FormData instance object, and this object is passed when passing.
  5. After the data is passed, it is encapsulated in request.FILES instead of request.POST

 

 
 
 

1 Save the file to the server locally

upload.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">

</head>
<body>

<form action="" method="post" enctype="multipart/form-data">
    {% csrf_token %}
    <div>用户名:<input type="text" name="username"></div>
    <div>头像<input type="file" name="avatar"></div>
    <input type="submit" value="提交">
</form>

</body>
</html>

urls.py

from django.conf.urls import url
from app01 import views

urlpatterns = [
    url(r'^upload',views.upload)
]

views.py

from django.shortcuts import render,HttpResponse

def upload(request):
    if request.method == 'POST':
        name = request.POST.get('username')
        avatar = request.FILES.get('avatar')

        with open(avatar.name,'wb') as f:
            for line in avatar:
                f.write(line)
        return HttpResponse('ok')

    return render(request,'upload.html')

Summarize

In this way, we have done a small example of basic file uploading. There are a few points to note here:

  1. csrf_token verification needs to be added to the form form
  2. The type value of the input box of the file is file
  3. To get the file in the view function, use the request.FILES.get() method
  4. The name of the file can be obtained through obj.name

2 Upload the file to the database

models.py

from django.db import models


class User(models.Model):
    username = models.CharField(max_length=16)
    avatar = models.FileField(upload_to='avatar')

views.py

def upload(request):
    if request.method == 'POST':
        name = request.POST.get('username')
        avatar = request.FILES.get('avatar')

        models.User.objects.create(username=name,avatar=avatar)
        return HttpResponse('ok')

    return render(request,'upload.html')

Summarize

The function of uploading files to the database has been implemented above. There are a few points to note:

  1. The so-called uploading to the database does not mean that the image itself or the binary code is placed in the database. In fact, it is also uploading the file to the local server. The database only stores the path of a file, so that when the user wants to call the file, he can go to the specified server through the path. location found
  2. When creating an ORM, the avatar field must have an attribute of upload_to='', specifying where the uploaded file is placed
  3. When adding to the database, the file field attribute assignment is the same in form as the ordinary field, such as: models.User.objects.create(username=name,avatar=avatar)
  4. If there are duplicate file names uploaded by two users, the system will automatically rename the file, and the effect is as follows:

additional

We have implemented the function. It seems that when we call the file, we only need to access the picture through the file itself that has been saved in the database file path, so that it appears on the web page. In fact, this is not the case.

We need to configure something so that django can find it, otherwise it will not pass the urls verification, and the reason why we can directly access the static files in static is because django has already configured it for us.

 

The configuration steps are as follows:

1. Configure in the site's setting.py

MEDIA_ROOT=os.path.join(BASE_DIR,"blog","media") #blog is the project name, media is the conventional folder name
 MEDIA_URL="/media/" # Similar to STATIC_URL, specifies that users can find files through this path

2. Configure in urls.py

from django.views.static import serve
from upload import settings #upload is the site name

url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
After configuration, you can access the picture through http://127.0.0.1:8001/media/milk.png

 

 3 Submit files with AJAX

upload.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>

<form>
    {% csrf_token %}
    <div>用户名:<input id="name-input" type="text"></div>
    <div>头像<input id="avatar-input" type="file"></div>
    <input id="submit-btn" type="button" value="提交">
</form>

<script src="/static/js/jquery-3.2.1.min.js"></script>
<script>
    $('#submit-btn').on('click',function () {
        formdata = new FormData();
        formdata.append('username',$('#name-input').val());

formdata.append("avatar",$("#avatar")[0].files[0]);
       formdata.append("csrfmiddlewaretoken",$("[name='csrfmiddlewaretoken']").val()); 
$.ajax({
processData:false,
contentType:false,
url:'/upload',
type:'post',
data:formdata,
success:function (arg) {
if (arg.state == 1){ alert('成功!') }else { alert('失败!') } } }) });
</script> </body> </html>

views.py

from django.shortcuts import render,HttpResponse
from django.http import JsonResponse
from app01 import models

def upload(request):
    if request.method == 'POST':
        name = request.POST.get('username')
        avatar = request.FILES.get('avatar')

        try:
            models.User.objects.create(username=name,avatar=avatar)
            data = {'state':1}
        except:
            data = {'state':0}

        return JsonResponse(data)

    return render(request,'upload.html')

Summarize

  1. When Ajax uploads, the tpye of the button must not use submit
  2. When Ajax uploads, the value of the data parameter is no longer a common 'dictionary' type value, but a FormData object
    • Create object formdata = new FormData();
    • Add the value formdata.append('username',$('#name-input').val());
  3. Ajax should add csrf verification when doing post submission
    • formdata.append("csrfmiddlewaretoken",$("[name='csrfmiddlewaretoken']").val());
  4. Finally, there are two parameter settings when Ajax uploads files
    • processData:false
    • contentType:false

4 There is a preview function when uploading image files

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>

<form>
    <!----Use a label tag to bind the upload file input box to the image,
          Clicking on the picture is equivalent to clicking the button to upload the file ---->
    <label><img id="avatar-img" src="/static/img/default.png" width="80px" height="80px">
        <div>头像<input id="avatar-input" hidden type="file"></div>
    </label>

    <input id="submit-btn" type="button" value="提交">
</form>

<script src="/static/js/jquery-3.2.1.min.js"></script>

<script>

    // Upload file button (image in label) click event
    $('#avatar-input').on('change',function () {
        // Get the last image selected by the user
        var choose_file=$(this)[0].files[0];
        // Create a new FileReader object to read file information
        var reader=new FileReader();
        // Read the path of the image uploaded by the user
        reader.readAsDataURL(choose_file);
        // After reading, modify the src attribute of the image to the local path of the image uploaded by the user
        reader.onload=function () {
             $("#avatar-img").attr("src",reader.result)
        }
    });

</script>

 5 Summary

For file upload, whether it is a direct form submission or Ajax submission, the fundamental problem is to tell the browser that you are uploading a file instead of a normal string

And how to tell the browser, that is, through the ContentType parameter of the request weight, we don't need to specify it when uploading a normal string, because it has a default value,

And if you want to upload files, you need to specify it separately. Summarize the following points

  1. If the form is uploaded, the  ContentType is specified by enctype="multipart/form-data" 
  2. For ajax upload, specify ContentType through   processData:false and contentType:false
  3. When the form is uploaded, the file data is ''wrapped'' data through the <input type="file"> tag,
  4. When ajax is uploaded, data is added through a FormData instance object, and this object is passed when passing.
  5. After the data is passed, it is encapsulated in request.FILES instead of request.POST

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325172318&siteId=291194637