问题
I HAD this situation:
Clicking on a html submit button, I call views.stream_response
which "activates" views.stream_response_generator
which "activates" stream.py and return a StreamingHttpResponse and I see a progressive number every second up to m
at /stream_response/
:
1
2
3
4
5
6
7
8 //e.g. 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'),
...
homepage/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 delete "8" and use only m = request.POST.get('numb')
I obtain:
ValueError at /stream_response/ The view homepage.views.stream_response didn't return an HttpResponse object. It returned None instead.
So, if I try to submit, it takes only the default value 8 (and works) but it not takes my form input. What is it 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()
homepage/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 as input e.g. 7 from keyboard:
KeyError at /stream_response/
'numero'
![]()
WHILE
If I write m = request.POST.get('numero')
, in command line I have:
...
My form html:
My Number: 7
m = 7
...
while len(lista) < m:
TypeError: unorderable types: int() < str()
回答1:
EDIT : ModelForm part removed, no need to save the data in DB so using classic form this way :
Method 1 : Classic Form without Model using Django
in your forms.py
from django import forms
class InputNumeroForm(forms.Form):
numero = forms.IntegerField()
in your 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 your 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 little there are two types of form in Django :
- Classic Forms which do not require saving in a database
- Model Forms which will allow you to create forms which are based on a Database Model i.e. (you can add a row to your db or edit one)
Here you don't need to save your number in your database so you use classical forms: https://docs.djangoproject.com/en/1.8/topics/forms/
Method 2 : Not using the 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 your 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>
回答2:
I see a handful of issues with the code you posted:
Your form field is missing the 'name' attribute, and thus the value set for this field will not be passed to your code. This is why your request.POST.get('numb')
returns None unless you provide your default (8).
Try this:
<input id="numb" name="numb" type="number" />
Also, I noticed in your form you use models.IntegerField
- why are you trying to use a model field here?
A better approach for you may be to add the numb field to your form and then retrieve the value from the form's cleaned data: form.cleaned_data['numb']
instead of the POST data.
Hopefully this gets you going.
回答3:
Django views MUST return a HttpResponse object. Considering that the other two functions you're referencing have only one line each, it would serve you better to just put everything in one function, or at least move the StreamingHttpResponse to the main function.
Edit: The StreamingResponseHttp must be given an iterable so, going back to the stream.py, try taking out the return and print functions (I've taken out excess stuff for experimentation's sake). This worked for me in the 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
来源:https://stackoverflow.com/questions/29921085/django-passing-value-from-template-to-view