Django: passing a value from a template to view

I had this situation:

By clicking on the html submit button, I call views.stream_response , which “activates” views.stream_response_generator , which “activates” stream.py and returns StreamingHttpResponse, and I see a progressive number every second up to m in /stream_response/

 1 2 3 4 5 6 7 8 //eg my default max value for m 

stream.py

 from django.template import Context, Template import time def streamx(m): lista = [] x=0 while len(lista) < m: x = x + 1 time.sleep(1) lista.append(x) yield "<div>%s</div>\n" % x #prints on browser print(lista) #print on eclipse return (x) 

views.py

 def stream_response(request): // unified the three functions as suggested if request.method == 'POST': form = InputNumeroForm(request.POST) if form.is_valid(): m = request.POST.get('numb', 8) resp = StreamingHttpResponse(stream.streamx(m)) return resp 

forms.py

 from django.db import models from django import forms from django.forms import ModelForm class InputNumero(models.Model): m = models.IntegerField() class InputNumeroForm(forms.Form): class Meta: models = InputNumero fields = ('m',) 

urls.py

 ... url(r'^homepage/provadata/$', views.provadata), url(r'^stream_response/$', views.stream_response, name='stream_response'), ... 

Home /provadata.html

 <form id="streamform" action="{% url 'stream_response' %}" method="POST"> {% csrf_token %} {{form}} <input id="numb" type="number" /> <input type="submit" value="to view" id="streambutton" /> </form> 

If I remove "8" and use only m = request.POST.get('numb') , I get:

ValueError at / stream_response / View homepage.views.stream_response does not return an HttpResponse object. Instead, None was specified instead.

So, if I try to submit, it only accepts the default value of 8 (and it works), but it does not accept my input form. What is this wrong?

→ UPDATE: with @Tanguy Serrat suggestions:

views.py

 def stream_response(request): form = InputNumeroForm() if request.method == 'POST': form = InputNumeroForm(data=request.POST) if form.is_valid(): #Accessing the data in cleaned_data m = form.cleaned_data['numero'] print("My form html: %s" % form) print ("My Number: %s" % m) #watch your command line print("m = ", m) resp = StreamingHttpResponse(stream.streamx(m)) return resp #If not post provide the form here in the template : return render(request, 'homepage/provadata.html', {'form': form,}) 

forms.py

 class InputNumeroForm(forms.Form): numero = models.IntegerField() 

Home /provadata.py

 <form action="/stream_response/" method="POST"> {% csrf_token %} {{form}} <!--issue: does not appear on the html !!!!!--> <input type="number" name="numero" /> <!--so I write this--> <input type="submit" value="to view" /> </form> 

If I give input, for example. 7 from the keyboard:

KeyError at / stream_response /

'Numero' It takes the input number

WHILE

If I write m = request.POST.get('numero') , on the command line I have:

 ... My form html: My Number: 7 m = 7 ... while len(lista) < m: TypeError: unorderable types: int() < str() 
+2
django django-forms django-views streaming
source share
3 answers

EDIT: Part of ModelForm is deleted, there is no need to save data in the database, so the classic form:

Method 1: Classic form without model using Django

in forms.py

 from django import forms class InputNumeroForm(forms.Form): numero = forms.IntegerField() 

in views.py

 from django.shortcuts import render def stream_response(request): form = InputNumeroForm() if request.method == 'POST': form = InputNumeroForm(data=request.POST) if form.is_valid(): #Accessing the data in cleaned_data m = form.cleaned_data['numero'] print "My Number %s" % m #watch your command line resp = StreamingHttpResponse(stream.streamx(m)) return resp #If not post provide the form here in the template : return render(request, 'homepage/provadata.html', { 'form': form, }) 

in the template:

 <form id="streamform" action="{% url 'stream_response' %}" method="POST"> {% csrf_token %} {{ form }} <input type="submit" value="to view" id="streambutton" /> </form> 

To clarify a bit, there are two types of forms in Django:

  • Classic forms that do not require storing in the database
  • Forms of models that allow you to create forms based on the database model (for example, you can add a line to your db or edit it)

Here you do not need to save your number in your database so that you use the classic forms: https://docs.djangoproject.com/en/1.8/topics/forms/

Method 2: Do not use a Django form For very simple forms like your case:

in views.py

 from django.shortcuts import render def stream_response(request): if request.method == 'POST': if request.POST.get('numero', False): m = int(request.POST['numero']) print "My Number %s" % m #watch your command line resp = StreamingHttpResponse(stream.streamx(m)) return resp return render(request, 'homepage/provadata.html') 

in the template:

 <form id="streamform" action="{% url 'stream_response' %}" method="POST"> {% csrf_token %} <input type="number" name="numero" /> <input type="submit" value="to view" id="streambutton" /> </form> 
+4
source share

Django views MUST return an HttpResponse object. Given that the other two functions you are referring to have only one line, it would be best for you to put everything in one function, or at least move StreamingHttpResponse to the main function.

Edit: StreamingResponseHttp must be set to an iterable, so returning to stream.py try to extract the return and print functions (I spent extra things for the sake of experimenting). This worked for me in a shell.

 def streamx(m): lista = [] x=0 while len(lista) < m: x = x + 1 time.sleep(1) lista.append(x) yield "<div>%s</div>\n" % x #prints on browser #c = Context({'x': x}) #yield Template('{{ x }} <br />\n').render(c) def stream_response(request): if request.method == 'POST': form = InputNumeroForm(request.POST) if form.is_valid(): m = request['numb'] resp = StreamingHttpResponse(streamx(m)) return resp 
0
source share

I see several problems with the code you submitted:

There is no attribute 'name' in the form field, and therefore the value set for this field will not be passed to your code. This is why your request.POST.get('numb') returns None if you did not specify your default value (8). Try the following:

 <input id="numb" name="numb" type="number" /> 

Also, I noticed that you are using models.IntegerField in your form - why are you trying to use the model field here?

The best approach for you might be to add a numb field to your form and then extract the value from the cleared form data: form.cleaned_data['numb'] instead of the POST data.

I hope you succeed.

0
source share

All Articles