Why the django form data cannot display after submitting - python

After submitting the form (input), it will redirect to another page(result) and show the form information in this result page.
The problem now is that the submitted information doesn't show in the result page.
I doubt the reason is because in result' views.py, I want to show the submitted form from Input,but the form's data is not saved or I shouldn't fetch the data from the model,I should fetch the data from view,so it cannot display the table:
context['input'] = Input.objects.all()
Please correct me if my guess is right or not. Thanks in advance for your suggestion.
input- models.py
class Input(models.Model):
company=models.CharField(max_length=100,default='Empty')
region=models.CharField(max_length=100,default='Empty')
start_date=models.DateField(auto_now=False, auto_now_add=False,default='Empty')
end_date=models.DateField(auto_now=False, auto_now_add=False,default='Empty')
input -- form
class Inputform(forms.ModelForm):
company=forms.CharField()
regionlist = forms.ModelChoiceField(queryset=Result.objects.values('region').distinct())
start_date=forms.DateField(widget=DateInput(),required=True)
end_date = forms.DateField(widget=DateInput(),required=True)
class Meta:
model = Input
fields = ('company', 'region','start_date','end_date')
widgets = {
'start_date': forms.DateInput(attrs={'class':'datepicker'}),
'end_date': forms.DateInput(attrs={'class':'datepicker'}),
}
input -- part of the html code
<form action="result_list/" method="post">{% csrf_token %}
<!--enter company-->
<div class="field">
<p>Company:<input type="text" name="Company" value="{{company}}"/>
</div>
<!--select region-->
<div class="field" >
<label> Select the Region:
{{ form.regionlist }}
{% for region in form.regionlist.choices %}
<option value="{{ val }}" {% ifequal data.val val %}selected {% endifequal %}></option>
{% endfor %}
</label>
</div>
....
<div class="fieldWrapper">
<p><input type="submit" value="Submit" /></p></div>
</form>
input --views
from django.http import HttpResponseRedirect
from django.shortcuts import render,render_to_response,get_object_or_404
from inputform.forms import Inputform
from inputform.models import Input
from result.models import Result
from django.views.decorators.csrf import csrf_exempt
from django.views.generic.list import ListView
#csrf_exempt
def input(request):
if request.method == 'POST':
form = Inputform(request.POST)
if form.is_valid():
cd = form.cleaned_data
print (cd['company'])
form.save()
return redirect('result')
urls
from inputform import views
from django.views.generic.list import ListView
from inputform.views import input
from django.views.generic import RedirectView
urlpatterns = patterns('',
url(r'^result_list/$',ResultView.as_view(),name='result'),
(r'^input/$', RedirectView.as_view(url='/result_list/')),
}
Result --views.py
class ResultView(ListView):
context_object_name = 'result_list'
template_name = 'result_list.html'
queryset = Result.objects.all()
def get_context_data(self, **kwargs):
context = super(ResultView, self).get_context_data(**kwargs)
context['input'] = Input.objects.all()
return context
Result -- html
{% for input_object in input %}
<table border="1" cellpadding="1">
<tr>
<td align="left">Company</td>
<td>{{input_object.company}}</td>
</tr>
<tr>
<td align="left">Region</td>
<td>{{input_object.region}}</td>
</tr>
...
</table>
{% endfor %}

Your code looks rather messy. Its not clear, how you initially pass the empty form to input template.
However, the problem may arise cause you do not pass the whole form to your template, but only {{ form.regionlist }}. So your inputs cannot write any data to db.
Render either the whole {{ form }} or each field one by one as you've done for regionlist field.
Moreover, you do not need to dublicate model field in forms.py if it does not actually override somehow the original field in models.py.

The root cause is actually in url.py:
Should delete "(r'^input/$', RedirectView.as_view(url='/result_list/')),",only to put redirect in views.py is enough.

Related

Fill out the form and save it in db base

I am working on a Django project and I want to fill out a form and save the data in the db database and then be able to show it on another page, I managed to create the form, following some tutorials, but it does not write me anything in the database. Here's how I currently have things:
forms.py
from django import forms
from .models import AusenciasForm
from django.contrib.auth.models import User
class AusenciasForm(forms.ModelForm):
class Meta:
model = AusenciasFormulario
fields = '__all__'
widgets = {'fecha': forms.DateInput(attrs={'type': 'date'})}
models.py
from django.db import models
from django.utils import timezone
import datetime
from django.contrib.auth.models import User
from django.urls import reverse
class AusenciasFormulario(models.Model):
#razon = models.ModelChoiceField(label="Razón", queryset=razones.object.all())
fecha = models.DateField(("Date"),default=datetime.date.today)#label="Fecha", required=True
razon = [
('Estudios/Examen','Estudios/Examen'),
('Enfermedad','Enfermedad'),
('Lesión','Lesión'),
('Motivos personales','Motivos personales'),
('Motivos familiares','Motivos familiares'),
('Otros','Otros')
]
motivo = models.CharField(max_length=100, choices=razon, default='Otros')
comentarios= models.CharField(max_length=200,blank=True)
jugador = User
views.py
class FormularioAusenciaView(HttpRequest):
def index(request):
ausencias_formulario = AuForm.objects.all()
return render(request, 'blog/ausencias.html', {'ausencias_formulario':ausencias_formulario})
def procesar_formulario(request):
#if request.method == 'POST':
form = AusenciasForm(request.POST)
if form.is_valid():
form.save()
form = AusenciasForm()
return HttpResponseRedirect('ausencias/') #Add your route name, where you want to go after form save
else:
form = AusenciasForm()
return render(request, 'blog/formularioAusencia.html', {'form':form})
Urls.py
from django.urls import path
from .views import PostListView, PostDetailView, PostCreateView, PostUpdateView, PostDeleteView,UserPostListView, FormularioAusenciaView, ausencias
from .import views
from django.contrib.auth.decorators import login_required
urlpatterns = [
path('', login_required(PostListView.as_view()), name='blog-home'),
path('user/<str:username>',login_required( UserPostListView.as_view()), name='user-posts'),
path('post/<int:pk>/',login_required( PostDetailView.as_view()), name='post-detail'),
path('post/new/',login_required( PostCreateView.as_view()), name='post-create'),
path('post/<int:pk>/update/',login_required( PostUpdateView.as_view()), name='post-update'),
path('post/<int:pk>/delete/',login_required( PostDeleteView.as_view()), name='post-delete'),
path('about/', views.about, name='blog-about'),
path('formularioAusencia/',login_required( FormularioAusenciaView.index), name='formularioAusencia'),
#path('asistencia_done/',formularioAusencia, name='asistencia_done'),
path('ausencias/',login_required( views.ausencias), name='ausencias'),
]
the template
{% extends "blog/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<div class="media">
<img class="rounded-circle account-img" src="{{ user.profile.image.url }}">
<div class="media-body">
<h2 class="account-heading">{{ user.username }}</h2>
<p class="text-secondary">{{ user.email }}</p>
</div>
</div>
{% if user.is_authenticated %}
<p></p><a class="mr-2">Rellenar si no vas a poder acudir a un próximo entrenamiento o partido</a></p>
<!--<label><input type="checkbox" id="cbox1" value="first_checkbox"></label><br>-->
<form method="POST" action="{% url 'ausencias' %}">{% csrf_token %}
{{ form|crispy }}
<button class="btn btn-danger btn-sm mt-1 mb-1" type="submit">Enviar</button>
</form>
</div>
<div class="form-group">
</div>
{% endif %}
</div>
{% endblock content %}
In forms.py:
You have imported wrong model name:
change this
from .models import AusenciasForm
To this:
from .models import AusenciasFormulario
And in views.py file:
You have not added any orm query so that's why it is not saving in db.
views.py :
Do this:
def index(request):
ausencias_formulario = AusenciasFormulario.objects.all() #Here i have retrieved data using orm
return render(request, 'blog/formularioAusencia.html', {'ausencias_formulario':ausencias_formulario})
def procesar_formulario(request):
if request.method == 'POST':
form = AusenciasForm()
if form.is_valid():
form.save()
return HttpResponseRedirect('/home/') #Add your route name, where you want to go after form save
else:
form = AusenciasForm()
return render(request, 'blog/formularioAusencia.html', {'form':form})
And in your templates:
formularioAusencia.html
<form method='post'>
{{form}}
<input type="submit" /> #Added new code here
</form>
After submitting above form, using below code, you will get that fields.
Add below code after the form tag.
To display all the fields to templates add the below code in template:
{% for field in ausencias_formulario %}
{{field.fecha}}
#Add remaining fields here to display
{% endfor %}

Django: after submitting the form, why the redirected url is an empty page

After submitting the form (input), it will redirect to another page(result).
The thing is it will indeed go to the desired url, but the content is empty. (It is not empty if I open it separately). Thanks for your suggestion in advance.
input -- url
from inputform import views
from django.views.generic.list import ListView
from inputform.views import input
from django.views.generic import RedirectView
urlpatterns = patterns('',
url(r'^result_list/$',ResultView.as_view(),name='result'),
(r'^input/$', RedirectView.as_view(url='/result_list/')),
}
input --views
from django.http import HttpResponseRedirect
from django.shortcuts import render,render_to_response,get_object_or_404
from inputform.forms import Inputform
from inputform.models import Input
from dupont.models import Result
from django.views.decorators.csrf import csrf_exempt
from django.views.generic.list import ListView
#csrf_exempt
def input(request):
if request.method == 'POST':
form = Inputform(request.POST)
if form.is_valid():
cd = form.cleaned_data
print (cd['company'])
form.save()
return redirect(reverse,('','result_list'))
Result --views.py
class ResultView(ListView):
context_object_name = 'result_list'
template_name = 'result_list.html'
queryset = Result.objects.all()
def get_context_data(self, **kwargs):
context = super(ResultView, self).get_context_data(**kwargs)
context['input'] = Input.objects.all()
return context
Result -- html
<form action="result_list/" method="post">{% csrf_token %}
<div class="field" >
<label> Select the Region:
{{ form.regionlist }}
{% for region in form.regionlist.choices %}
<option value="{{ val }}" {% ifequal data.val val %}selected {% endifequal %}></option>
{% endfor %}
</label>
</div>
<div class="fieldWrapper">
<p><input type="submit" value="Submit" /></p></div>
</form>
As mentioned in the comments the correct parameter to pass to reverse() is 'result', i.e the name of the url.
If you're using django 1.7 or higher you can skip the reverse part and django will do it automatically for you.
def input(request):
if request.method == 'POST':
form = Inputform(request.POST)
if form.is_valid():
cd = form.cleaned_data
print (cd['company'])
form.save()
return redirect('result')
should work for you

HTML tags for choicefield in Django

I cant seem to find ANYWHERE on how to do choicefield HTML tags in Django. I found radio buttons and other advance choice fields, but nothing on basic drop down HTML tags with Django. I have models.py and view.py set up passing list1 to the html pages, but cant seem to make it display anything except
<select style="width:300px">
{% for choice in list1.VIEWS %}
<option>{{choice}}</option>
{{choice}}
{% endfor %}
</select>
Help would be greatly appreciated
models.py
class preset_list(models.Model):
VIEWS = (
('1', 'X'),
('2', 'Y'),
)
query_choice = forms.ChoiceField(choices=VIEWS)
view.py
list1 = models.preset_list()
return render_to_response('services.html',
{'array':json.dumps(data, cls=SpecialEncoder),
'list1':list1},
)
ModelForms are your friend here.
models.py
class PresetList(models.Model):
VIEWS = (
('1', 'X'),
('2', 'Y'),
)
query_choice = forms.ChoiceField(choices=VIEWS)
forms.py
from django.forms import ModelForm
from . import models
class PresetListForm(ModelForm):
class Meta:
model = models.PresetList
view.py
from . import forms
def my_view(request):
preset_form = forms.PresetListForm()
return render_to_response('services.html', {
'array': json.dumps(data, cls=SpecialEncoder),
'preset_form': preset_form,
})
services.html
<form method=POST action="/somewhere">
{{ preset_form.as_p }}
</form>
https://docs.djangoproject.com/en/dev/topics/forms/modelforms/
https://docs.djangoproject.com/en/1.6/ref/forms/fields/#choicefield
Give the generic CreateView a try.
views.py
from django.views.generic.edit import CreateView
from .models import PresetList
class PresetListCreate(CreateView):
model = PresetList
presetlist_form.html
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Create" />
</form>
we can use this without using django form
<select style="width:300px" name="presen">
{% for val, name in preset_list.VIEWS %}
<option value="{{val}}">{{name}}</option>
{% endfor %}
</select>
Not sure what you want done, but if you eant to send 1 when X is displayed, the following should work:
<select style="width:300px">
{% for choice in list1.VIEWS %}
<option value={{choice.0}}>{{choice.1}}</option>
{{choice}}
{% endfor %}
</select>
You can create a form with a drop-down and tell it which values to populate it with like so:
Form
class MyDropDownForm(forms.ModelForm):
somerow = forms.ModelChoiceField(
# change this queryset if you want to limit the options
queryset= MyModel.objects.all().values('somerow'),
widget=Select(),
required=True,
)
class Meta:
model = MyModel
fields = ['somerow']
View
class MyView(DjangoTemplateView):
def get(self, request):
# you can set an instance when creating the form to set the value
# to be that of an existing row in your model
# MyDropDownForm(instance=MyModel.objects.filter(id=1))
form = MyDropDownForm()
return render_to_response('app/page.html', {'form': form})
def post(self, request):
# if you had set the instance in the get you want to do that again
form = MyDropDownForm(data=request.POST)
if form.is_valid():
return render_to_response('app/success.html')
return render_to_response('app/page.html', {'form': form})
Page.html
<form method="post">
{% csrf_token %}
{{ form.id }}
{{ form.myrow }}
{% if form.myrow.errors %}
{% for error in form.myrow.errors %}<p>{{ error }}</p>{% endfor %}
{% endif %}
<button>Submit</button>
</form>
Take a look at the docs here for more info on creating model forms.

Saving data using Django ModelForms

I used this code previously it worked fine and i was suggested to use ModelForm by another member, it did make sense to use the form.is_valid() function etc.. so thought of giving it a try.
I went through some other examples on the internet but mine does not seem to work for some reason, or may be I am not doing it right, I get the following when I print the form in the view, and it goes to the else statement, so my form does not get saved
<input id="id_product" type="text" name="product" value="aassddf" maxlength="250" />
FAIL
My model.py
from django.db import models
from django.forms import ModelForm
class Category(models.Model):
name = models.CharField(max_length=250)
def __unicode__(self):
return self.name
class Product(models.Model):
category = models.ForeignKey(Category)
product = models.CharField(max_length=250)
quantity = models.IntegerField(default=0)
price = models.FloatField(default=0.0)
def __unicode__(self):
return self.product
class ProductForm(ModelForm):
class Meta:
model = Product
My views.py
from models import *
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
def index(request):
...
...
def add_product(request):
if request.method == 'POST':
form = ProductForm(request.POST)
print form['product']
if form.is_valid():
form.save()
return HttpResponseRedirect('/product')
else:
print 'FAIL'
return HttpResponseRedirect('/product')
My html
<form method="post" action="add_product/">
{% csrf_token %}
<label for="category">Category</label>
<select name="category" id="category">
{% for category in category_list %}
<option> {{ category.name }} </option>
{% endfor %}
</select>
<label for="product">Product</label>
<input type="text" name="product" id="product">
<label for="quantity">Quantitiy</label>
<input type="text" name="quantity" id="quantity">
<label for="price">Price</label>
<input type="text" name="price" id="price">
<input type="submit" value="Add New product" id="create">
</form>
Is there a better way i could save the data, using ModelForms ??
Thanks in advance for the help.
You should read the documentation. If the form is not valid, it will have a whole set of errors associated with it, which will tell you exactly why. But you just throw that away, and redirect to /product. The docs show exactly how to redisplay the form with the errors.
Also you should not write HTML form field tags directly in your template: use the form object from the view - {{ form.product }}, etc - as these will be repopulated with the appropriate values on redisplay.
Thanks to Daniel Roseman and Anuj Gupta I think I finally re-worked on my code on got it working in a standard way so it will generate the html form and validate errors.
So for anyone else who is trying to work django forms here is the code I worked on.
My model.py is was almost the same one i posted on the question but i removed
class ProductForm(ModelForm):
class Meta:
model = Product
I created a new form.py here is the code-
from django import forms
from models import Category
class ProductForm(forms.Form):
# Put all my Categories into a select option
category = forms.ModelChoiceField(queryset=Category.objects.all())
product = forms.CharField()
quantity = forms.IntegerField()
price = forms.FloatField()
My views.py changed had a lot of changes -
def add_product(request):
success = False
if request.method == "POST":
product_form = ProductForm(request.POST)
if product_form.is_valid():
success = True
category = Category.objects.get(name=product_form.cleaned_data['category'])
product = product_form.cleaned_data['product']
quantity = product_form.cleaned_data['quantity']
price = product_form.cleaned_data['price']
new_product = Product(category = category, product = product, quantity = quantity, price = price )
new_product.save()
new_product_form = ProductForm()
ctx2 = {'success':success, 'product_form':new_product_form}
return render_to_response('product/add_product.html', ctx2 , context_instance=RequestContext(request))
else:
product_form = ProductForm()
ctx = {'product_form':product_form}
return render_to_response('product/add_product.html', ctx , context_instance=RequestContext(request))
Finally in my html page i used {{ product_form.as_p }} so it created the forms dynamically
{% if success %}
<h3> product added successfully </h3>
{% endif %}
<form method="post" action=".">
{% csrf_token %}
{{ product_form.as_p }}
<input type="submit" value="Add New product" id="create">
<input type="reset" value="reset" id="reset">
</form>
This may not be the perfect solution, but for a starter like me this sounds good, and at times you just get lost while reading the docs lol, hope it helps some one.
Cheers
Try:
<form method="post" action="add_product/">
{% csrf_token %}
{{ form.as_p }}
</form>
in your template, instead of hand-coding the form's input tags. This shortcut will generate the form html for you, as well as print validation errors.
Make sure you return the form object to the template when:
There is no request.POST (form has not been submitted)
form.is_valid() fails (form has validation errors)
Of course, this is only to get you started. You really should read the docs

Getting empty form in Django with MetaForm

I have this as template account_form.html
<form action="/contact/" method="post">
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }}: {{ field }}
</div>
{% endfor %}
<p><input type="submit" value="Send message" /></p>
</form>
My model.py
class Account(models.Model):
person_name = models.CharField(max_length=30)
account_number = models.IntegerField()
creation_date = models.DateField()
My View is
def account_form(request):
if request.method == 'POST': # If the form has been submitted...
form = AccountForm(request.POST) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
# Process the data in form.cleaned_data
# ...
return HttpResponseRedirect('/thanks/') # Redirect after POST
else:
form = AccountForm() # An unbound form
return render_to_response('account_form.html', {
'form': form,
})
The problem is when i load the page i only get the submit button nothing else
I think you forgot to actually create your form:
Should read something like this:
forms.py:
from django.forms import ModelForm
from yourapp.models import Account
class AccountForm(ModelForm):
class Meta:
model = Order
This will give you all fields from Account.
HTH

Categories

Resources