Trying To Pass A Javascript Variable Named 'context' To An HTML Form In Django

Hi, I am using JavaScript code to access my laptop’s camera, and then I am using HTML code to have the user click a button which takes a picture, and then sends that picture to another HTML template which is then rendered.

In the source code below, the button that needs to accomplish this when clicked is called “Camera”.

Can someone please explain how I can pass the Javascript variable called ‘context’ to another HTML file after clicking the button called “Camera”. I appreciate any help. Thank you.

I am attaching an image that shows how the facial-login.html template looks inside the browser (with the laptop webcam covered).

The following is the source code inside the facial-login.html file:

{% load static %}
<!DOCTYPE html>
<html>
<head>
    <title>Webcam</title>

    <style>
        .video-wrap
        {
            /*Setting the margin to 'auto' will position the box to be in the exact center
            of the web page.*/
            margin: auto;
            left: 0;
            right: 0;
            position: absolute;

            /*We are setting the dimensions of the box that will contain the camera.*/
            width: 450px;
            height: 450px;
            border: 10px solid greenyellow;
            text-align: center;
            /*width/height of box = 430px(camera width) + 10px*2 (total border width) = 450px*/
        }

        .camera-button
        {
            position: relative;
            top: 460px;
            text-align: center;
        }

        h2 
        {
            text-align: center;
        }
    </style>

    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="{% static 'facial-login-style.css' %}" type="text/css"/>
</head>
<body>

<div class="text">
    <h2>Image Recognition Login</h2>
</div>

<!-- <div class="facial-login-video-background">
    <video autoplay loop muted plays-inline class="facial-video">
        <source src="{% static 'video.mp4' %}" type="video/mp4">
    </video>
</div> -->

<div class="video-wrap">
    <video id="video" playsinline autoplay muted></video>
</div>

<div class="camera-button">
    <span id="newline">
        <font size="+2" style="color:greenyellow">Click the 
            <span class="glyphicon glyphicon-camera"></span> button to take a facial 
            image of yourself (be sure to look straight into the camera).</font>
    </span>

    <form action="facial-login-result" method="POST" id="systemForm">
        {% csrf_token %}
        <div id="snap">
            <button type="submit" name="system" value="{{ context }}" form="systemForm">
                <a href="{% url 'facial-login-result' %}" class="btn btn-info btn-lg">
                    <span class="glyphicon glyphicon-camera"></span> Camera
                </a>
            </button>
        </div>
    </form>

    <a href="{% url 'facial-login-result' %}" class="btn btn-info btn-lg"> -->
        <button onClick="myFunction()">Click me</button>
    </a>
</div>

<span id="newline"></span>

<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

<canvas id="canvas" width="430" height="430"></canvas>

<p id="demo"></p>

<script>

'use strict'; // Use the 'strict' mode of Javascript.

const video = document.getElementById('video');
const canvas = document.getElementById('canvas');
const snap = document.getElementById('snap');
const errorMsgElement = document.getElementById('span#ErrorMsg');

const constraints =
{
    audio: true,
    video:
    {
        width: 430, height: 430
    }
};

async function init()
{
    try
    {
        const stream = await navigator.mediaDevices.getUserMedia(constraints);
        handleSuccess(stream);
    }
    catch(e)
    {
        errorMsgElement.innerHTML = `navigator.getUserMedia.error:${e.toString()}`;
    }
}

function handleSuccess(stream)
{
    window.stream = stream;
    video.srcObject = stream;
}

init();


var context = canvas.getContext('2d');

function myFunction()
{
    document.getElementById("demo").innerHTML = context;
}

snap.addEventListener("click", function()
{
    // drawImage(image, xCoordinate, yCoordinate, recWidth, recHeight)
    context.drawImage(video, 23, video.height, 430, 430);
});

</script>

</body>
</html>

You don’t pass a variable to “an HTML file”. You submit data to a Django view. That Django view returns a response to the browser. That response may or may not include HTML. (e.g. it might just be JSON in the case of an AJAX call.)

I can’t be more specific here because it’s not clear what you’re really trying to accomplish at this point.

Is the end result of clicking this button going to cause a whole page refresh? If so, then you may want to submit the data as POST data to the view. Otherwise, this might be better suited as an AJAX call to submit the data as a JSON object.

Also, a JavaScript context may not be directly usable by Django without some work - you might want to convert it to an image, and send the image data only.

You might also want to send the image data as if it were a file being uploaded and not just a form field.

You’ll also want to fully understand what you’re going to do with this data after it has been submitted. (For example, if your JavaScript is sending this as a JPG, but your Django view needs it as a PNG, you’re creating more work for yourself than if you just had JavaScript submit it as a PNG.)

So you have a few options to be considered before deciding on a final approach.

Hi. I have made some progress on this, but still have many questions.

The following is the facial-login.html file:

{% load static %}
<!DOCTYPE html>
<html>
<head>
    <title>Webcam</title>

    <style>
        .video-wrap
        {
            /*Setting the margin to 'auto' will position the box to be in the exact center
            of the web page.*/
            margin: auto;
            left: 0;
            right: 0;
            position: absolute;

            /*We are setting the dimensions of the box that will contain the camera.*/
            width: 450px;
            height: 450px;
            border: 10px solid greenyellow;
            text-align: center;
            /*width/height of box = 430px(camera width) + 10px*2 (total border width) = 450px*/
        }

        .camera-button
        {
            position: relative;
            top: 460px;
            text-align: center;
        }

        h2 
        {
            text-align: center;
        }
    </style>

    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="{% static 'facial-login-style.css' %}" type="text/css"/>
</head>
<body>

<div class="text">
    <h2>Image Recognition Login</h2>
</div>

<!-- <div class="facial-login-video-background">
    <video autoplay loop muted plays-inline class="facial-video">
        <source src="{% static 'video-backgrounds/kapadokya.mp4' %}" type="video/mp4">
    </video>
</div> -->

<div class="video-wrap">
    <video id="video" playsinline autoplay muted></video>
</div>

<div class="camera-button">
    <span id="newline">
        <font size="+2" style="color:greenyellow">Click the 
            <span class="glyphicon glyphicon-camera"></span> button to take a facial 
            image of yourself (be sure to look straight into the camera).</font>
    </span>

    <!--'action' specifies where to send the data when the form is submitted.
        ''
        -->
    <form action="facial-login-result.html" method="POST">
        {% csrf_token %}
        <div id="snap">
            <button type="submit" value="{{ context }}">
                <a href="{% url 'facial-login-result' %}" class="btn btn-info btn-lg">
                    <span class="glyphicon glyphicon-camera"></span> Camera
                </a>
            </button>
            <!-- <button type="submit" name="system" value="{{ context }}" form="systemForm">
                <a href="{% url 'facial-login-result' %}" class="btn btn-info btn-lg">
                    <span class="glyphicon glyphicon-camera"></span> Camera
                </a>
            </button> -->
        </div>
    </form>

    <!-- <a href="{% url 'facial-login-result' %}" class="btn btn-info btn-lg">
        <button onClick="myFunction()">Click me</button>
    </a> -->
</div>

<span id="newline"></span>

<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

<canvas id="canvas" width="430" height="430"></canvas>

<p id="demo"></p>

<script>

'use strict'; // Use the 'strict' mode of Javascript.

const video = document.getElementById('video');

var canvas = document.getElementById('canvas');

/*toDataURL() returns a data URL containing a representation of
  the image in the format specified by the type parameter.*/
var dataURL = canvas.toDataURL(type, encoderOptions);

const snap = document.getElementById('snap');
const errorMsgElement = document.getElementById('span#ErrorMsg');

const constraints =
{
    audio: true,
    video:
    {
        width: 430, height: 430
    }
};

async function init()
{
    try
    {
        const stream = await navigator.mediaDevices.getUserMedia(constraints);
        handleSuccess(stream);
    }
    catch(e)
    {
        errorMsgElement.innerHTML = `navigator.getUserMedia.error:${e.toString()}`;
    }
}

function handleSuccess(stream)
{
    window.stream = stream;
    video.srcObject = stream;
}

init();


var context = canvas.getContext('2d');

function myFunction()
{
    document.getElementById("demo").innerHTML = context;
}

snap.addEventListener("click", function()
{
    // drawImage(image, xCoordinate, yCoordinate, recWidth, recHeight)
    context.drawImage(video, 23, video.height, 430, 430);
});

function convertCanvasToImage() {
  let canvas = document.getElementById("canvas");
  let image = new Image();
  image.src = canvas.toDataURL();
  return image;
}

let pnGImage = convertCanvasToImage();
document.appendChild(pnGImage);

</script>

</body>
</html>

In this file, I am trying to get the image captured by the camera, convert it to a png image, and send it to a Django view.

I am wondering how I can improve the code in this file to accomplish this. I appreciate any guidance with this.

Is this code working? Or are you still having problems with it?

What sort of “improvements” are you looking for?

From a purely “code organization” perspective, my initial recommendation would be to separate the JavaScript, CSS, and template/HTML into separate files, but that’s a personal preference on my part.

I see your point. I do not believe that the current code is working properly.

What I am going to do is find a simpler solution that will allow me to access my laptop’s camera and click a button that will take a picture.

Then I will find a way to save that picture as an image and submit it as form data.

Can I submit form data to a view function from an HTML page in Django?

Yes, absolutely. I don’t have any JavaScript doc references handy, but it can be done.

Edit: See HTMLFormElement.submit() - Web APIs | MDN as a starting point.

I am trying to capture an image of someone with the computer’s camera, save it as a PNG image, and then send it to a view function.

I have found some source code for this at the following link:

The following source code is what I have so far:

<!doctype html>

<head>
    <style>
    #video {
        border: 1px solid black;
        width: 320px;
        height: 240px;
    }

    #photo {
        border: 1px solid black;
        width: 320px;
        height: 240px;
    }

    #canvas {
        display: none;
    }

    .camera {
        width: 340px;
        display: inline-block;
    }

    .output {
        width: 340px;
        display: inline-block;
    }

    #startbutton {
        display: block;
        position: relative;
        margin-left: auto;
        margin-right: auto;
        bottom: 36px;
        padding: 5px;
        background-color: #6a67ce;
        border: 1px solid rgba(255, 255, 255, 0.7);
        font-size: 14px;
        color: rgba(255, 255, 255, 1.0);
        cursor: pointer;
    }

    .contentarea {
        font-size: 16px;
        font-family: Arial;
        text-align: center;
    }
    </style>
    <!--The title of the HTML document.-->
    <title>Facial Image Recognition</title>
</head>

<body>
    <div class="contentarea">
        <h1>Facial Image Recognition</h1>

        <div class="camera">
            <video id="video">Video stream not available.</video>
        </div>
        <!--An id on a <button> tag assigns an identifier to the button.
            The id allows JavaScript to easily access the <button> element
            and manipulate it.
            When a user clicks on the "Capture Image" button, the -->
        <div><button id="startbutton">Capture Image</button></div>
        
        <!-- <div>
        <a href="{% url 'facial-login-result' %}" id="startButton" 
           class="btn btn-info btn-lg">
           <span class="glyphicon glyphicon-camera"></span>Capture Image
        </a>
        </div> -->

        <!--The HTML canvas tag is where the image frames are stored
            before they are converted into an image of proper format
            to be shown using the <img> tag.-->
        <canvas id="canvas"></canvas>

        <div class="output">
            <img id="photo" alt="The image captured will appear in this box.">
        </div>
    </div>

    <script>

    (function() {

        // We will scale the photo width to this.
        var width = 320;
        // The height will be computed based on the input stream.
        var height = 0;

        var streaming = false;

        var video = null;
        var canvas = null;
        var photo = null;
        var startbutton = null;

        function startup() {
            video = document.getElementById('video');
            canvas = document.getElementById('canvas');
            photo = document.getElementById('photo');

            /*The following line is executed when a user clicks on the
              "Capture Image" button.
              
              document.getElementById returns the element whose 'id'
              is 'startbutton'.*/
            startbutton = document.getElementById('startbutton');

            // Access the video stream from the webcam.
            navigator.mediaDevices.getUserMedia({
                video: true,
                audio: false
            })
            // Upon success, stream video in a video tag.
            .then(function(stream) {
                video.srcObject = stream;
                video.play();
            })
            .catch(function(err) {
                console.log("An error occurred: " + err);
            });

            video.addEventListener('canplay', function(ev) {
                if (!streaming) {
                    height = video.videoHeight / (video.videoWidth / width);

                    if (isNaN(height)) {
                        height = width / (4 / 3);
                    }

                    video.setAttribute('width', width);
                    video.setAttribute('height', height);
                    canvas.setAttribute('width', width);
                    canvas.setAttribute('height', height);
                    streaming = true;
                }
            }, false);

            startbutton.addEventListener('click', function(ev) {
                takepicture();
                ev.preventDefault();
            }, false);

            clearphoto();
        }

        /*Collect the frames of the photo from the canvas and then
          convert it into a PNG format, so that it can be shown in
          the HTML page.*/
        function clearphoto() {
            var context = canvas.getContext('2d');
            context.fillStyle = "#AAA";
            context.fillRect(0, 0, canvas.width, canvas.height);

            var data = canvas.toDataURL('image/png');

            photo.setAttribute('src', data);
        }

        /*Capture a frame from the video stream.*/
        function takepicture() {
            var context = canvas.getContext('2d');
            if (width && height) {
                canvas.width = width;
                canvas.height = height;
                context.drawImage(video, 0, 0, width, height);

                /*toDataURL('image/png') returns a data URL containing a
                  representation of the image in PNG format.*/
                var data = canvas.toDataURL('image/png');

                /*'src' is the name of the attribute whose value is to be set.
                  'data' is a string containing the value to assign to the attribute.*/
                photo.setAttribute('src', data);
            } else {
                clearphoto();
            }
        }

        /*The following code will call the startup() function when
          the HTML page is loaded.*/
        window.addEventListener('load', startup, false);
    })();
    </script>
</body>

</html>

My first question is where is the image that was captured from the computer’s camera?

Was it assigned to the variable ‘data’ or was it assigned to the variable ‘photo’?

I would like to find a way to pass the image to a view which can then pass it to another HTML template.