简体   繁体   中英

How to get jQuery range slider value into form to store in database in Django

The user have to be able to submit and save the value of the range slider 1 . The purpose is that the user guesses how full an object is in real life and then can report back as part of a game the filling percentage. The user interface is in the picture below.

Currently I can retrieve the data from the POST form (in the slider.html) as a preset 'value' but not the range slider value. I have looked much around, the problem is i'm not familiar enough with Javascript to implement the solution. I'm thinking one can fetch the value from the javascript function and directly tot he POST html form? Can anyone help suggesting how to do that or any other suggestions? This is the code so far, it's a bit of a mess because of many try and errors

Models.py

from django.db import models
from django.forms import ModelForm
from django import forms


class Measurements(models.Model):
    DeviceId            = models.IntegerField(blank=True, null=True)
    TimeStamp           = models.DateTimeField(auto_now=True)
    Metadata            = models.IntegerField(blank=True, null=True)
    Sensor              = models.IntegerField(default=False)
    Button              = models.IntegerField(default=False)
    QrUser              = models.IntegerField(default=True)
    FillingPercentage   = models.DecimalField(max_digits=4, decimal_places=2, blank=True, null=True)
    slider_value        = models.IntegerField(default=False, null=True, blank=True)



def __str__(self):
    return str(self.DeviceId)

class Meta:
    verbose_name_plural = "Measurements"     

Forms.py

from django.forms import ModelForm
from django import forms

from .models import Measurements

class MeasurementsForm(ModelForm):
    class Meta:
        model = Measurements
        fields = ('FillingPercentage','slider_value')
        widgets = {'slider_value' : forms.HiddenInput()}    

def clean_FillingPercentage(self):
    print("fUNCTION CALLED")
    value = self.cleaned_data.get('something_else')
    print(value)


class IntegerFieldForm(forms.Form):
    field5 = forms.IntegerField(
        help_text="Filling percentage", widget=forms.NumberInput(attrs={'type': 'range', 'min': '0', 'max': '100'}))

Views.py

from django.shortcuts import render
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
from django.views.generic import FormView, TemplateView, CreateView
import floppyforms as forms


from .forms import MeasurementsForm


class QRView(CreateView):
    form_class = MeasurementsForm
    template_name = 'QrFill/slider.html'
    success_url = '/guess/'

    def form_valid(self, form):
        instance = form.save(commit=False)
        # instance.FillingPercentage = self.request
        return super(QRView, self).form_valid(form)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context ['FillingPercentage'] = 'Add Fill Level'
        return context

    def read_value():
        FillingPercentage = self.request.POST.get('FillingPercentage')
        if FillingPercentage is not None:                
            instruction_task_values.insert(0, FillingPercentage) 
        print('\n\n\nThis is your instruction_task_values in 1 %s', instruction_task_values)




def my_view(request):
# if this is a POST request we need to process the form data
    if request.method == 'POST':
        # create a form instance and populate it with data from the request:
        form = MeasurementsForm(request.POST)
        # check whether it's valid:
        if form.is_valid():
            # process the data in form.cleaned_data as required
            slider_value = form.cleaned_data['slider_value']
            if slider_value is not None:    
                instruction_task_values.insert(0, slider_value)

            # redirect to a new URL:
            return HttpResponseRedirect('/thanks/')

    # if a GET (or any other method) we'll create a blank form
    else:
        form = MeasurementsForm()

    return render(request, 'QrFill/slider.html', {'form': form})

slider.html

{% load staticfiles %}

{% load bootstrap4 %}

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>rangeslider.js</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="{% static 'css/rangeslider.css' %}"/>
    <style>
        *,
        *:before,
        *:after {
            -webkit-box-sizing: border-box;
               -moz-box-sizing: border-box;
                    box-sizing: border-box;
        }
        html {
            color: #404040;
            font-family: Helvetica, arial, sans-serif;
        }
        body {
            padding: 50px 20px;
            margin: 0 auto;
            max-width: 800px;
        }
        output {
            display: block;
            font-size: 30px;
            font-weight: bold;
            text-align: center;
            margin: 30px 0;
            width: 100%;
        }
        .u-left {
            float: left;
        }
        .u-cf:before,
        .u-cf:after {
            content: "";
            display: table;
        }
        .u-cf:after {
            clear: both;
        }
        .u-text-left {
            text-align: left;
        }
    </style>
</head>
<body>



    <div>

        <div>

             <form method='POST' class='form'> 
            {% csrf_token %}

                <input type="hidden" name="slider_value" id="myVar" value="50" id="hidden1"/> 




                <input type="range" min="0" max="100" step="0.01" value="50" data-rangeslider>

                <output id='output'> </output>

                <button type="submit" name="_submit" class="btn btn-primary btn-lg">Submit</button>

        </div>


    </div>



    <script src="//localhost:8080"></script>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>

    <script src="{% static 'js/rangeslider.js' %}"></script>


    <script >
        var myVar = document.getElementById("myVar").value;


    $(function() {


        var $document = $(document);
        var selector = '[data-rangeslider]';
        var $element = $(selector);
        var textContent = ('textContent' in document) ? 'textContent' : 'innerText';
        function valueOutput(element) {
            var value = element.value + "%";
            var output = element.parentNode.getElementsByTagName('output')[0] || element.parentNode.parentNode.getElementsByTagName('output')[0];
            output[textContent] = value;
        }
        $document.on('input', 'input[type="range"], ' + selector, function(e) {
            valueOutput(e.target);
        });



        $element.rangeslider({
            polyfill: false,
            onInit: function() {
                valueOutput(this.$element[0]);
            },
            onSlide: function(position, value) {
            },
            onSlideEnd: function(position, value) {

                $("#amount").text(value);
                console.log("Value: " + value.toString())
                FillingPercentage = value.toString()



            }
        });
    });
    </script>
</body>
</html>

I'll give you an idea about how to do it.

You should create a new simple view which will look like save_progress(request) .

def save_progress(request):
    progress = request.POST.get('progress')
    ...do with it what you want...

Than create url in the same way path('app_name/..path../save-progress/', views.save_progress, name='save-progress') . So now you wi'll have the url and view defined, co you can write the javascript controller

var timeout = null;
function saveProgress() {
    clearTimeout(timeout);
    timeout = setTimeout(function() {
        $.ajax({
            method: 'POST',
            url: '{% url "save-progress" %}'
            data: {progress: $('#slider-id-to-be-saved').val()},
            success: function(response) {
                console.log('Yeah! Your data were sent and saved!');
            }
        })
    }, 500); // so it will wait 500ms until it actually sends the POST 
}

and add the onchange listener to the input range

<input type="range" min="0" max="100" step="0.01" value="50" data-rangeslider onchange="saveProgress">

This is the idea of it. Notice the timeout, so your data will be sent actually after it does not change for a while.

Thanks a lot for the input.

I solved it like the code posted below, however, it would be more ideal to make the post by the user clicking on a submit button.. Any suggestions on how to improve to that?

in slide.html

$(function() {
var $document = $(document);
var selector = '[data-rangeslider]';
var $element = $(selector);
var timeout = null;
var textContent = ('textContent' in document) ? 'textContent' : 'innerText';

function valueOutput(element) {
    var value = element.value + "%";
    var output = element.parentNode.getElementsByTagName('output')[0] || element.parentNode.parentNode.getElementsByTagName('output')[0];
    output[textContent] = value;
    clearTimeout(timeout);
    timeout = setTimeout(function() {
        $.ajax({
        method: 'POST',
        url: '{% url "QrFill:save-progress" %}',
        data: {progress: element.value
        },
        success: function(response){
            console.log('Yeah! Your data were sent and saved!');
        }, timeout: 2000
    })
    }, 3000);     
}

views.py

@csrf_exempt
def edit_favorites(request):
    if request.is_ajax():
        post_text = request.POST.get('progress')
        post = Measurements(FillingPercentage=post_text)
        post.save()
    else:
        message = "Not Ajax"
    return HttpResponse(message)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM