Online Document Scanning Using Python Django and Dynamic Web TWAIN
Django is a popular Python framework for web development. In this tutorial, we will create a web application using Django and Dynamic Web TWAIN.
This article is Part 4 in a 5-Part Series.
- Part 1 - Building Web Document Scanning Applications with ASP.NET Core MVC
- Part 2 - How to Scan and Upload Documents with Dynamic Web TWAIN and Node.js
- Part 3 - Scanning and Uploading Documents with Dynamic Web TWAIN and Go
- Part 4 - Online Document Scanning Using Python Django and Dynamic Web TWAIN
- Part 5 - How to Scan and Upload Documents in PHP Laravel Project
Prerequisites
- Python
-
Django
python -m pip install Django python -m django --version - Dynamic Web TWAIN Trial License
Overall Steps
To integrate Django with Dynamic Web TWAIN, follow these steps:
- Create a Django project.
- Inside the project, create a Django app.
- Develop an HTML template to load the Dynamic Web TWAIN library, utilizing the template syntax to dynamically generate the library path.
- Configure the static resource files’ path.
Creating Your Project with Django
Open your terminal to initiate a Django project using the following command (applicable to Windows, Linux, and macOS):
python -m django startproject djangodwt Upon completion, you’ll find the newly created project folder within your working directory.

Next, navigate into the djangodwt directory and launch the app using the command below:
cd djangodwt python manage.py runserver Once the server starts successfully, open http://127.0.0.1:8000 in your web browser.

With these steps, you’ve successfully set up a simple Django project.
Integrating with Dynamic Web TWAIN
Creating the App
To develop your web scanner application, you should first create an app within your Django project.
python manage.py startapp dwt Note: In Django, “project” and “app” have distinct meanings. An app is a web application that performs specific functions, whereas a project is a collection of apps that together comprise a particular website.
After this step, your project structure will look like this:
djangodwt - djangodwt - __pycache__ - asgi.py - settings.py - urls.py - wsgi.py - __init__.py - dwt - migrations - __init__.py - admin.py - apps.py - models.py - tests.py - views.py - __init__.py - db.sqlite3 - manage.py Creating the View for Dynamic Web TWAIN
To develop our view, we will utilize a template. Conventionally, your template files should reside in {project_folder/templates/{app_named_folder}/}. Let’s create one named index.html.
<!DOCTYPE html> <head> <title>Dynamic Web Twain</title> <meta charset="utf-8"> {% load static %} {% csrf_token %} <script type="text/javascript" src="{% static 'dynamsoft.webtwain.initiate.js' %}"></script> <script type="text/javascript" src="{% static 'dynamsoft.webtwain.config.js' %}"></script> <script type="text/javascript" src="{% static 'jquery-3.6.0.min.js' %}"></script> </head> <body> <div id="app"> <div id="dwtcontrolContainer"></div> <button onclick="scan()">Scan</button> </div> <script type="text/javascript"> var dwtObjct; window.onload = function () { if (Dynamsoft) { Dynamsoft.DWT.AutoLoad = false; Dynamsoft.DWT.UseLocalService = true; Dynamsoft.DWT.Containers = [{ ContainerId: 'dwtcontrolContainer', Width: '640px', Height: '640px' }]; Dynamsoft.DWT.RegisterEvent('OnWebTwainReady', Dynamsoft_OnReady); // https://www.dynamsoft.com/customer/license/trialLicense/?product=dcv&package=cross-platform Dynamsoft.DWT.ProductKey = 'LICENSE-KEY'; Dynamsoft.DWT.ResourcesPath = 'static'; Dynamsoft.DWT.Load(); } }; function Dynamsoft_OnReady() { dwtObjct = Dynamsoft.DWT.GetWebTwain('dwtcontrolContainer'); } function scan() { if (dwtObjct) { dwtObjct.SelectSourceAsync().then(function () { return dwtObjct.AcquireImageAsync({ IfCloseSourceAfterAcquire: true // Scanner source will be closed automatically after the scan. }); }).catch(function (exp) { alert(exp.message); }); } } </script> </body> Note that you’ll need a valid license key. Make sure to replace LICENSE-KEY with your own to activate the scanner API. The ResourcesPath should be the path to the dynamsoft.webtwain.initiate.js and dynamsoft.webtwain.config.js files, which we’ll address later.
Next, let’s edit the file dwt/views.py by adding the following Python code:
from django.http import HttpResponse, request from django import template from django.shortcuts import render import os def index(request): return render(request, 'dwt/index.html') Within the app folder {project_folder}/dwt, we create a file named urls.py and insert the code below:
from django.urls import path from . import views urlpatterns = [ path('', views.index, name='index') ] Then, we navigate to the project’s urls.py file located in {project_folder}/{project_name} and include the newly defined URL rules:
from django.contrib import admin from django.urls import include, path urlpatterns = [ path('admin/', admin.site.urls), path('', include('dwt.urls')) ] Lastly, let’s configure the templates directory in settings.py by specifying the template DIR as follows:
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], # this field 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] Importing Dynamic Web TWAIN
It’s now time to integrate Dynamic Web TWAIN’s resource files into this project.
Steps:
- Under the project root, create a
staticfolder. - Within the
staticfolder, create adwtfolder. - From
<Dynamic Web TWAIN SDK PATH>/Resources, copy the resource files to thestatic/directory.
Next, add the following code to settings.py to ensure the static/ directory is accessible:
STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR, "static") ] With these steps, your web document scanning application using Dynamic Web TWAIN and Django should now be operational.


How to Upload Documents in Django
Let’s incorporate the front-end code to enable the uploading of scanned documents to the server.
function upload() { dwtObjct.HTTPPort = 8000; var CurrentPathName = unescape(location.pathname); // get current PathName in plain ASCII var CurrentPath = CurrentPathName.substring(0, CurrentPathName.lastIndexOf("/") + 1); var strActionPage = CurrentPath + "upload"; var strHostIP = "127.0.0.1"; var OnSuccess = function (httpResponse) { alert("Succesfully uploaded"); }; var OnFailure = function (errorCode, errorString, httpResponse) { alert(httpResponse); }; var date = new Date(); var csrftoken = getCookie('csrftoken'); dwtObjct.SetHTTPFormField('csrfmiddlewaretoken', csrftoken); dwtObjct.HTTPUploadThroughPostEx( strHostIP, dwtObjct.CurrentImageIndexInBuffer, strActionPage, date.getTime() + ".jpg", 1, // JPEG OnSuccess, OnFailure ); } function getCookie(name) { var cookieValue = null; if (document.cookie && document.cookie != '') { var cookies = document.cookie.split(';'); for (var i = 0; i < cookies.length; i++) { var cookie = jQuery.trim(cookies[i]); if (cookie.substring(0, name.length + 1) == (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } The upload function is responsible for sending the scanned image to the server. It utilizes the HTTPUploadThroughPostEx method for the upload process. The SetHTTPFormField method is designated to set the form field for the CSRF token, while the getCookie function retrieves the CSRF token from the cookie.
On the server side, uploaded documents can be managed in dwt/views.py:
from django.http import HttpResponse, request from django import template from django.shortcuts import render import os from .models import Image def index(request): return render(request, 'dwt/index.html') def upload(request): if request.method == 'POST': image = Image() image.name = request.FILES['RemoteFile'].name image.data = request.FILES['RemoteFile'] image.save() return HttpResponse("Successful") return HttpResponse("Failed") def handle_uploaded_file(file, filename): if not os.path.exists('upload/'): os.mkdir('upload/') with open('upload/' + filename, 'wb+') as destination: for chunk in file.chunks(): destination.write(chunk) return destination Source Code
https://github.com/yushulx/web-twain-document-scan-management/blob/main/examples/python_upload