Welcome to Blogs @ Andrew Qu
Blog Index
All blogs
Search results

Learning Django - Part 2

Summary

Django is a web framework using Python programming language. Using Django and an appropriate web server, you can build and host websites. This post is Part 2 of my learning Django project.

Adding Static Files

Continue from Part 1Static files include javascript files, image files, download files etc. Django has special rules to locate these files. You add these files to the "static" folder of each application. In the template file, you use {{ STATIC_URL }} to refer to all root "static" folders in each application.

To the KeysApp application, we will add 2 files, jquery-1.11.1.min.js and keysapp.js.

jquery-1.11.1.min.js will be used for all applications in the project. Therefore, it will be placed under "DjDemo/static". This is a project level setting. Therefore, setting.py need to be modified as below:

STATICFILES_DIRS = (
    "C:/Users/djwwwroot/DjDemo/static/",
)

keysapp.js is used by KeysApp only. Therefore, it is placed under "KeysApp/static". This file is not visible to other applications in the project.

To include the files in an html template, write:

    <script src="{{ STATIC_URL }}jquery-1.11.1.min.js" type="text/javascript"></script>
   <script src="{{ STATIC_URL }}keysapp.js" type="text/javascript"></script>

To complete the task, add a new file, KeysApp/statis/keysapp.js with the following contents:

function kv_page_loaded() {
   alert("Page loaded");
}
function validate_keyname() {
   v = $("input[name=kn]").val();
   if( v.length < 3 ) {
      alert("Key name is too short (min 3 chars) !");
      return false;
   }
   return true;
}
Here, $("input[name=kn]").val() is using jQuery to find the input field with name = "kn" and get its input value.

Modify kv_page.html as follows:
<head>
    <title>Key and values</title>
    <script src="{{ STATIC_URL }}jquery-1.11.1.min.js" type="text/javascript"></script>
    <script src="{{ STATIC_URL }}keysapp.js" type="text/javascript"></script>
</head>
<body onload="kv_page_loaded();">
....
    <form onsubmit="return validate_keyname();" method="post"
       enctype="multipart/form-data" action="{% url 'create' %}" >
       {% csrf_token %}
       Key name : <input type="text" name="kn" style="width:200px;"/><br />
       Key value : <input type="text" name="kv" style="width:200px;" /><br />
       <input type="submit" name="send" value="Create New Key" />
    </form>
Now refresh the page: http: //localhost:8000/keys/, you should see an alert box when the page is loaded. If you enter a key name that is less than 3 chars long, a dialog will be displayed and the form will not be submitted.

Uploading File

Next task is to upload a file to the server. First, we need to define the model. In models.py, add the following code:

import os
class Document(models.Model) :
   docfile = models.FileField(upload_to='uploaded_files')
   upload_dtm = models.DateTimeField('upload time', auto_now=True)
   original_name = models.CharField(max_length=120)
   saved_name = models.CharField(max_length=120)

   def filename(self) :
      return os.path.basename(self.docfile.path)

   def __unicode__(self):
      retstr = self.original_name[:20] + "-" + self.saved_name[:30]
      if len(self.original_name) > 20 : retstr += "..."
      return retstr

Modify admin.py by adding:

from KeysApp.models import Document
...
admin.site.register(Document)

Resync database with : python manage.py syncdb
This will create a new table, Document in the database. The files will be saved to MEDIA_ROOT/uploaded_files. MEDIA_ROOT is specified in settings.py. upload_files is given when defining the docfile = models.FieField.

Modify KeysApp/urls.py to add:
    url(r'^upload/$', views.upload_file, name='upload'),
This maps http: //localhost:8000/keys/upload/ to views.upload_file() function to be added to views.py :
from KeysApp.models import Document

def upload_file(request) :
   # request to display the upload file page
   if request.method != 'POST' :
      t = loader.get_template("upload.html")
      c = RequestContext(request)

      return HttpResponse(t.render(c))
   else :
      # Upload (post) a selected file
      files = request.FILES.getlist('upfiles')
      for f in files :
         newdoc = Document(docfile = f)
         newdoc.saved_name = newdoc.filename()
         newdoc.save()
      if len(files) == 1 :
         return HttpResponse("File saved successfully at " + newdoc.filename())
      else :
         return HttpResponse(str(len(files)) + " Files saved successfully.")

Add a new file KeysApp/Templates/upload.html with the following contents:

<html>
<head>
    <title>Upload file</title>
    <script src="{{ STATIC_URL }}jquery-1.11.1.min.js" type="text/javascript"></script>
    <script src="{{ STATIC_URL }}keysapp.js" type="text/javascript"></script>
</head>
<body>
<table style="margin-left:auto; margin-right:auto;" >
    <tr><td colspan='2'>
    <form  method="post" enctype="multipart/form-data">
       {% csrf_token %}
       Select file to upload <br />
       <input type="file" name="upfiles" style="width:500px;" multiple /><br /><br />
       <input type="submit" name="upload" value="Upload File" />
    </form>
    </td></tr>
</table>
</body>
</html>

This includes a standard html form that can upload multiple files. In views.upload_file(), the files are passed to request.FILES as a list.

Now browse to http: //localhost:8000/keys/upload, you should be able to upload files. Check files are uploaded to MEDIA_ROOT/uploaded_files folder

Dynamic File Download

Let's see how to download a file that is dynamically generate on the server. Of course, we can treat it as a static file and put a link on the returned page. But this will have to ask the user to click to download. We want the download to happen automatically.

Modify views.py as follows:
def upload_file(request) :
   # request to display the upload file page
   if request.method != 'POST' :
      t = loader.get_template("upload.html")
      c = RequestContext(request)
      return HttpResponse(t.render(c))
   else :
      # Upload (post) a selected file
      files = request.FILES.getlist('upfiles')
      for f in files :
         newdoc = Document(docfile = f)
         newdoc.saved_name = newdoc.filename()
         newdoc.save()
      if len(files) == 1 :
         retstr = "File saved successfully at " + newdoc.filename()
         response = HttpResponse(retstr, mimetype='application/octet-stream')
         response['Content-Disposition'] = 'attachment; filename=notice.txt'
         response['content-length'] = str(len(retstr))
         return response
      else :
         return HttpResponse(str(len(files)) + " Files saved successfully.")
Now if you upload a file, on return, the browser will ask you to save a file. Unfortunately, this does not work in Internet Explorer.

I added a new function, and a corresponding url, as follows:

views.py
def download_test(request) :
    retstr = "A temporary file to be saved by the browser."
    response = HttpResponse(retstr, mimetype='application/octet-stream')
    response['Content-Disposition'] = 'attachment; filename=notice.txt'
    response['content-length'] = str(len(retstr))
    return response
url.py
    url(r'^download/$', views.download_test, name='download'),
This works in IE. (But this is of course not a solution or workaround. I will update when a solution is found). Source code download Download full source code
Ads from Google
Dr Li Anchor Profi
www.anchorprofi.de
Engineering anchorage plate design system
©Andrew Qu, 2015. All rights reserved. Code snippets may be used "AS IS" without any kind of warranty. DIY tips may be followed at your own risk.