In those years, the pitfalls we step on in Django web development (1) -- the magical '/' and ajax + iframe uploads, djangoiframe
1. upload images and display them at the front end
To avoid the overall front-end refreshing, we use ajax + iframe (compatible with all browsers) for uploading, so that users can see the image immediately after uploading:
Before uploading:
After uploading:
Front-end html:
<form>MIDDLEWARE_CLASSES = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',]
Django prevents cross-site request forgery by Using middleware django. middleware. csrf. CsrfViewMiddleware. The anti-Cross-Site Request Forgery function in django is divided into global and local.
Global:
Middleware django. middleware. csrf. CsrfViewMiddleware
Partial:
- @ Csrf_protect: forces the anti-Cross-Site Request Forgery feature for the current function, even if no global middleware is set in settings.
- @ Csrf_exempt: cancels the current function's Cross-Site Request Forgery Prevention function, even if global middleware is set in settings.
Middleware'Django. middleware. csrf. CsrfViewMiddleware ',Check whether the post request carries a token. If not, return directly in process_request and report the following error:
At this time, we have several Processing Methods: 1. comment out the csrf middleware in settings. 2. add @ csrf_exempt to the views function that receives the post request (Note: from django. views. decorators. csrf import csrf_exempt, csrf_protect), which means to cancel the current function anti-Cross-Site Request Forgery function;
JavaScript code:
Function UploadImage (ths) {document. getElementById ('upload _ img_iframe '). onload = UploadImageComplete; // After the page is loaded, execute the UploadImageComplete function document.getelementbyid('upload_img_form'assist.tar get = 'upload_img_iframe '; // set form to submit to iframe document. getElementById ('upload _ img_form '). submit (); // # submit to iframe} function UploadImageComplete () {var origin = $ ("# upload_img_iframe "). contents (). find ("body "). text (); // # obtain the image data var obj = JSON. parse (origin); // # convert to JavaScript Object var img = document. createElement ('img '); // # create an img tag. src = obj. path; // image address img. style. width = "200px"; img. style. height = "180px"; $ ("# upload_img_form "). append (img); // Add an image $ ('# fakeFile '). addClass ('hide '); $ (' # reuploadimage '). removeClass ('hide '); $ (' # fakeFile '). find ('input [type = "text"] '). val (obj. data); // # Save the image address to the hidden input tag}
Backend views function code:
Def upload (request): if request. method = 'post': obj = request. FILES. get ('img ') # get image object pat = OS. path. join ('static ', 'img', 'vote', obj. name) # file opening Directory, which must be consistent with the current file path f = open (pat, 'wb') for ch in obj. chunks (): f. write (ch) f. close () ret = {'path': '/' + OS. path. join ('static ', 'img', 'vote', obj. name)} # django front-end file path: '/' + static file prefix static + directory under static file import json return HttpResponse (json. dumps (ret) # return render(request,'upload.html ',)
The background and front-end js have a pitfall on file path reproduction:
Note: Save the image in img under static file directory (the prefix of the static file path is also static)
The path we want to introduce the image to the django front-end is:/static/img/xx.png. Note that '/' must be added before static, this magic '/' represents the main directory of the current program, that is, BASE_DIR in the configuration file.
In the background, we open the file and write the image to the server path. Here, the open path must follow the python rules instead of the django front-end rules, that is, python will start searching from the current path by default, therefore, you can directly static/img/xx.png without adding '/'.
II. The database query results give feedback to the front-end about serialization
Json Cannot serialize data structures such as datatime and Decimal in django. solution:
1. Convert to python data structure separately
str( Decimal('12.36'))
Then serialize the data using json.
2. directly convert the QuerySet object of the database query result to a list. QuerySet looks like a list.
Ret = list (QuerySet object)
Result = json. dumps (ret)
Since the datetime date cannot be processed in json. dumps, you can use a custom processor for expansion, such:
import json from datetime import date from datetime import datetime class JsonCustomEncoder(json.JSONEncoder): def default(self, field): if isinstance(field, datetime): return o.strftime('%Y-%m-%d %H:%M:%S') elif isinstance(field, date): return o.strftime('%Y-%m-%d') else: return json.JSONEncoder.default(self, field) # ds = json.dumps(d, cls=JsonCustomEncoder)
This is achieved by developing json. dumps serialized classes.
3. Use the serialization tool serializers of django
from django.core import serializers ret = models.BookType.objects.all() data = serializers.serialize("json", ret)
Summary: common form upload files may be shared by everyone. Therefore, this blog post mainly describes some issues that need to be paid attention to when uploading files through ajax + iframe. For example, you need to use form to upload files, contact me. Thank you!