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.

Prerequisites

Overall Steps

To integrate Django with Dynamic Web TWAIN, follow these steps:

  1. Create a Django project.
  2. Inside the project, create a Django app.
  3. Develop an HTML template to load the Dynamic Web TWAIN library, utilizing the template syntax to dynamically generate the library path.
  4. 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.

Django 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.

new Django project

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=dwt
        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:

  1. Under the project root, create a static folder.
  2. Within the static folder, create a dwt folder.
  3. From <Dynamic Web TWAIN SDK PATH>/Resources, copy the resource files to the static/ 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.

Web document scan by Python Django

Web document management by Python Django

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