I believe the best way to learn is to do it multiple times with multiple scenarios. Other than the official tutorial program provided by Djangoproject.com, a book written by William S. Vincent is very useful too. The tile is Django for Beginners Learn web development with Django 2.0, and here is the free link.
Following through the entire book, I was able to replicate its newspaper app/website. What’s really valuable of this book is that it’s very hand-on, and incrementally progressing to more complex functions, and also provide guidance on how to test, how to save up in git and how to deploy via Heroku.
This blog will be focusing on my attempt to figure out these three nitty-gritty intricacies: 1. file path – where are the files stored across github, heroku server and client end; 2. upload and download file with Django’s managing files function; 3. reverse, reverse_lazy – how to use them.
First, about file path, the question is that anytime there is data uploaded or edited, they have to be stored somewhere. Django provides SQLite3 to manage the data. In the previous blog, I cited a block of shell commands to play around. For more complex situation, the uploadcsv app for instance, it allows users to upload csv files, Django provides a path of media folder to store these files when I run locally. In the indexweighting app, we set the file_path in views.py (wr.save(os.path.join(“static/files”, request.FILES[‘input_data’].name)); file_path = os.path.join(“static/files/”, request.FILES[‘input_data’].name)), and rendered it in return line (), so in the index.html file, simply “a href=”/{{file_path}}”>Download” will do the trick of displaying a download button, and allow the views to grab the data from that file_path. I assume when it is deployed in heroku server laid out with the same tree-like folder structure. Note in Django, uploaded file smaller than 2.5 megabytes are stored in memory, if it gets larger, Django will write the file to a temporary file in a temporary directory like /tmp/tmpzfp6I6.upload.
Second, upload and download files with Django’s managing files function. Django.core.files contains simple functions to apply files. for example:
>>> from django.core.files import File
# Create a Python file object using open()
>>> f = open(‘/path/to/hello.world’, ‘w’)
>>> myfile = File(f)
What’s more, in models, there is filefield function to use to upload files, take uploadcsv app’s model.py as an example:
from django.db import models
# Create your models here.
class Document(models.Model):
docfile = models.FileField(upload_to=’documents/%Y/%m/%d’)
There is the Form.py file too
from django import forms
class DocumentForm(forms.Form):
docfile = forms.FileField(
label=’Select a file’,
help_text=’max. 42 megabytes’
)
The upload function is achieved in the views.py, in which, the file is in request.FILES, queriable by request.FILES[‘file’], note that the request method has to be set “POST” and the positing the request has the attribute enctype = “multipart/form-data”, the same example view file is as follows:
from django.shortcuts import render from django.template import RequestContext from django.http import HttpResponseRedirect from django.urls import reverse from myapp.models import Document from myapp.forms import DocumentForm def list(request): # Handle file upload if request.method == 'POST': form = DocumentForm(request.POST, request.FILES) if form.is_valid(): newdoc = Document(docfile = request.FILES['docfile']) newdoc.save() # Redirect to the document list after POST return HttpResponseRedirect(reverse('list')) else: form = DocumentForm() # A empty, unbound form # Load documents for the list page documents = Document.objects.all() # Render list page with the documents and the form return render(request, 'list.html', {'documents': documents, 'form': form})
For download button to work, referencing the fine answer from stackoverflow,
import os from django.conf import settings from django.http import HttpResponse, Http404 def download(request, path): file_path = os.path.join(settings.MEDIA_ROOT, path) if os.path.exists(file_path): with open(file_path, 'rb') as fh: response = HttpResponse(fh.read(), content_type="application/vnd.ms-excel") response['Content-Disposition'] = 'inline; filename=' + os.path.basename(file_path) return response raise Http404
In the real practice of indexweighting, this line in the html file shows the surface layout: Download, it calls to the path and triggers the action of downloading.
Actually djangoproject has official materials on “outputting csv“.