Display form content on same template django - django

So I am working on django, I have a simple form with one text field named "sujet", here's the form.py code:
from django import forms
class ContactForm(forms.Form):
sujet = forms.CharField(max_length=100,
widget=forms.TextInput(
attrs={
'id': 'id_sujet',
'style': 'border-color: blue;',
'placeholder': 'Write your name here'
}
)
)
The template "contact.html" where the user can fill the form is the following:
<form id="myForm" action="{% url 'contact' %}" method="post">
{{ form.sujet }}
<input type="submit" value="Submit" />
</form>
<div id="response">
Sujet : <span id="sujeet"></span>
{{ sujet }}
</div>
In my "views.py" I want my contact function to render the variable "sujet" to the template so I can diplay it on "contact.html" after filling and submitting the form (the intended usage of this is later to display the result of the database query that concerns sujet and not the variable itself but I am still working on that), here's the code of the view function :
def contact(request):
form = ContactForm(request.POST or None)
if form.is_valid():
sujet = form.cleaned_data['sujet']
envoi = True
return redirect(request.META['HTTP_REFERER'], {'sujet':sujet})
else:
return render(request, 'voirkpi/contact.html', locals())
Here is the code of my "urls.py" :
from django.urls import path
from django.conf.urls import url
from . import views
urlpatterns = [
path('accueil', views.ligneerabstat),
path('spark', views.kpitest),
path('testchart', views.testchart),
path('contact', views.contact, name='contact'),
#path('test', views.test, name='test'),
url('test', views.test, name='test')
]
My problem is that after clicking submit sujet is empty and doesn't show anything, I did make this work with simple javascript, but that's not what I want as the intended usage of this is as I said later to query a database and return in that span the result of the query according to the "sujet" filled.
Any help would be very much appreciated, thank you.

Thanks for the help. You're right Resley Rodrigues, I solved my problem by changing my contact function in "views.py" like so:
def contact(request):
form = ContactForm(request.POST or None)
if form.is_valid():
sujet = form.cleaned_data['sujet']
envoi = True
form = ContactForm()
return render(request,'voirkpi/contact.html',locals(), {'sujet' : sujet})
else:
return render(request, 'voirkpi/contact.html', locals())

Related

How to create a record from request GET data (form does not pass the validation)

I am confused when I try to insert record from a "GET" request
I will try to explain what I want to do.
I am creating an application to take inventory of assets.
I have 3 tables in my database.
I have a main table called
fixed asset("ActFijo") where all the assets of my company are registered.
Another call Inventory ("Inventario"), which stores the name of each inventory
and another call Inventory_detail ("Inventario_detalle"), where the details or assets in which they are being counted are stored to verify that the equipament or furniture is not being stolen in that location.
From the main table ("ActFijo") I have to search for the furniture or asset and store it in the detail table ("Inventario_detalle")
I'm confused I don't know how to work on a GET request and then do a POST all in one request
Do I have to write my code in parts in a GET request and then POST?
Or can I do everything in the GET request?
This is the code I have so far
I don't know if it's ok, please I need guidance
For example my code does not pass the validation of the form.
if form.is_valid():
I am trying to print, But I don't see any validation error, it doesn't print anything
print(form.errors)
Views.py
from django.shortcuts import redirect, render
from .form import InventarioDetalle_Form, InventarioForm
from .models import ActFijo, Inventario, Inventario_detalle
# Create your views here.
def inventario_home_view(request):
if request.method == "GET":
inv = Inventario.objects.all()
context = {"inventarios": inv}
return render(request, "inventario/index.html", context)
def inventario_crear_view(request):
if request.method == "POST":
form = InventarioForm(request.POST)
if form.is_valid():
form.save()
return redirect("inventario-home")
else:
form = InventarioForm()
inv = Inventario.objects.all()
context = {"formulario": form, "inventarios": inv}
return render(request, 'inventario/crear.html', context)
def inventario_detalle_view(request, inventario):
if request.method == "GET":
# Obtener el valor del input "Buscar"
codigo_activo = request.GET.get("buscar")
print("[CODIGO ACTIVO]:", codigo_activo)
# Buscar el activo en la bd por el campo codigo
try:
activo = ActFijo.objects.get(codigo=codigo_activo)
# print(activo)
except ActFijo.DoesNotExist:
activo = None
if activo:
form = InventarioDetalle_Form(instance=activo)
# print(form)
print(form.errors)
if form.is_valid():
instance = form.save(commit=False)
instance.inventario_id = inventario
instance.save()
else:
print(
"This request does not pass the validation")
else:
print(
"The element does not exist")
context = {"item": Inventario_detalle.objects.all()}
return render(request, "inventario/detalle.html", context)
form.py:
from django import forms
from .models import Inventario, Inventario_detalle
class InventarioForm(forms.ModelForm):
class Meta:
model = Inventario
fields = '__all__'
class InventarioDetalle_Form(forms.ModelForm):
class Meta:
model = Inventario_detalle
fields = '__all__'
url.py
from django.urls import path
from django import views
from . import views
urlpatterns = [
path("", views.inventario_home_view, name="inventario-home"),
path("create/", views.inventario_crear_view,
name="inventario-create"),
path('detail/<int:inventario>',
views.inventario_detalle_view, name="inventario-detail"),
]
detail.html
{% extends "core/base.html" %} {% block content%}
<div class="container-fluid">
<div class="row">
<div class="col-md-12">
<div class="titulo mt-5">
<h1>Inventario Detalle</h1>
</div>
<form method="get">
<input type="text" class="form-control" placeholder="Buscar Activo" name="buscar" />
</form>
<div style="overflow-x: auto">
<table>
<thead>
<tr>
<th>Codigo</th>
<th>Descripcion</th>
<th>Accion</th>
</tr>
</thead>
<tbody>
{% for i in item %}
<tr>
<td>{{i.codigo}}</td>
<td>{{i.descripcion}}</td>
<td><button type="button" class="btn btn-danger">Eliminar</button></td>
</tr>
</tbody>
{% endfor %}
</tbody>
</table>
</div>
<div>{{request.GET}}</div>
</div>
</div>
</div>
{% endblock %}
The problem is here
def inventario_detalle_view(request, inventario):
if request.method == "GET":
codigo_activo = request.GET.get("buscar")
print("[CODIGO ACTIVO]:", codigo_activo)
try:
activo = ActFijo.objects.get(codigo=codigo_activo)
print(activo)
except ActFijo.DoesNotExist:
activo = None
if activo:
form = InventarioDetalle_Form(instance=activo)
print(form.errors)
if form.is_valid():
instance = form.save(commit=False)
instance.inventario_id = inventario
instance.save()
else:
print(
"This request does not pass the validation")
else:
print(
"The element does not exist")
context = {"item": Inventario_detalle.objects.all()}
return render(request, "inventario/detalle.html", context)
I believe you don't see any validation errors on the form because for the GET request, you are not passing in anything. The only thing you're passing into the form is the model instance and you're running form.is_valid on it which does not make sense. You dont need to use the form at all. Use this instead.
def inventario_detalle_view(request, inventario):
if request.method == "GET":
codigo_activo = request.GET.get("buscar")
print("[CODIGO ACTIVO]:", codigo_activo)
try:
activo = ActFijo.objects.get(codigo=codigo_activo) # get activo object
activo.inventario_id = inventario # update object
activo.save() # save changes
print(activo)
except ActFijo.DoesNotExist:
# you can do anthing here
# maybe redirect with a message..
pass
context = {"item": Inventario_detalle.objects.all()}
return render(request, "inventario/detalle.html", context)

Django-forms: Raise forms.ValidationError not working

I am beginner in Django and recently studied form-validation. I implemented the code but was unable to raise ValidationError for some constraints.
Here are my subsequent file content.
forms.py
from django import forms
from django.core import validators
class formClass(forms.Form):
name = forms.CharField(max_length=128)
email = forms.EmailField(max_length=256)
text = forms.CharField(widget=forms.Textarea)
catchBot = forms.CharField(required=False, widget=forms.HiddenInput,
validators=[validators.MaxLengthValidator(0)])
def clean(self):
cleaned_data = super(formClass, self).clean()
t = self.cleaned_data.get('name')
if t[0].lower() != 'd':
raise forms.ValidationError('Name must start with d.')
return cleaned_data
views.py
from django.shortcuts import render
from formApp import forms
from django.http import HttpResponseRedirect
def formNameView(request):
formObj = forms.formClass()
formDict = {'form': formObj}
if request.method == 'POST':
formObj = forms.formClass(request.POST)
if formObj.is_valid():
# SOME CODE
print("NAME: " + formObj.cleaned_data['name'])
print("EMAIL: " + formObj.cleaned_data['email'])
return HttpResponseRedirect('/users')
return render(request, 'formApp/forms.html', context=formDict)
My valid input works great, but it doesn't happen with my invalid input.
for example: if name = 'Alex', it should raise an error. But it doesn't.
Could someone please help me in it?
EDIT:
[Added forms.html and validators callable.]
Previously, I used validators callable to raise ValidationError instead of clean() method. But the results were same.
Here is my code:
def checkForD(value):
if value[0].lower() != 'd':
raise forms.ValidationError('Name must start with d.')
.
.
.
# in my formClass()
name = forms.CharField(max_length=128, validators[checkForD])
...
Forms.html
<body>
<div class='container'>
<div class='jumbotron'>
<h3>Welcome to the form page.</h3>
<h2>Please insert the form.</h2>
</div>
<form method="post">
{{form.as_p}}
{% csrf_token %}
<input type="submit" value="Submit" class="btn btn-primary"/>
</form>
</div>
</body>
In your POST block you've redefined formObj to be the bound form, but you haven't replaced the instance in the context dict - so what is passed to the template is the empty unbound form, and no errors will be shown on that template.
The easiest fix would be to move the definition of the dict to the end of the function:
formDict = {'form': formObj}
return render(request, 'formApp/forms.html', context=formDict)
Now the correct instance will be used and the errors will show.
You can try this: don't define the formDict in post, directly define it in return render
return render(request, 'formApp/forms.html', {'form': formObj})

The form editing the existing form does not save and redirects to wrong. Django

I'm trying to add an edit form to an existing model, but it does not save every time and redirects me to the home page instead of the 'account' page. What am I doing wrong? why changes in the existing model are not visible? any help will be appreciated.
views.py
def account(request):
data_now = datetime.datetime.now().strftime("%Y-%m-%d")
#my form
time = get_object_or_404(Time, pk=52)
if request.method == "POST":
form = TimeEditForm(request.POST, instance=time)
if form.is_valid():
time = form.save(commit=False)
time.save()
return redirect('account')
else:
form = TimeEditForm(instance=time)
context = {'data_now': data_now, 'time_edit_form': form}
return render(request, 'account.html', context)
forms.py
class TimeEditForm(forms.ModelForm):
class Meta:
model = Time
fields = ('compartment',)
labels ={
'free_or_no': 'field name in my language?'
}
models.py
class Time(models.Model):
day_time = models.ForeignKey(DayTime, on_delete=models.CASCADE)
compartment = models.CharField(max_length=11)
free_or_no = models.BooleanField(default=True)
time_equivalent = models.IntegerField()
urls.py
urlpatterns = [
url(r'^$', views.masseur_detail, name='masseur_detail'),
url(r'^account$', views.account, name='account')
]
account.html
<form action="." method="post">
{% csrf_token %}
{{ time_edit_form|crispy }}
<button type="submit" class="btn btn-block btn-primary"> Save</button>
</form>
This is quite a subtle issue.
Usually in Django it's recommended to use URLs that end with a slash - eg "/account/" - but your URL is just "/account", without the slash.
Now, when you put action="." in your form, the browser interprets this as "post to the root of the current directory". If your URL did end with a slash, that would be resolve to the same page. But because it doesn't, the browser posts to the root itself, ie "/".
The best solution is to change your URL pattern to r'^account/$'; alternatively (but not recommended) you could change your form to use action="".

Django custom form validation in ListView

I am using a ListView to set a form and to show results. However i am not sure how can I make form validation and having the same form with errors in case form.is_valid() is not True.
this is my code
forms.py
class InsolventiForm(forms.Form):
anno_validator = RegexValidator(r'[0-9]{4}', 'L\'anno deve essere un numero di 4 caratteri')
anno = forms.CharField(label='Anno', required=True, max_length=4,validators=[anno_validator])
def clean_anno(self):
anno = self.cleaned_data['anno']
return anno
views.py
from .forms import InsolventiForm
class InsolventiView(LoginRequiredMixin, ListView):
template_name = 'insolventi.html'
model = Archivio
form_class = InsolventiForm
def get(self, request):
import datetime
if self.request.GET.get('anno'):
form = self.form_class(self.request.GET)
if form.is_valid():
date = '31/12/'+self.request.GET.get('anno')
dateTime = datetime.datetime.strptime(date, "%d/%m/%Y")
dateC = '01/01/'+self.request.GET.get('anno')
dateTimeC = datetime.datetime.strptime(dateC, "%d/%m/%Y")
context = Archivio.objects.filter(~Q(quoteiscrizione__anno_quota__exact=self.request.GET.get('anno')) \
& Q(data_iscrizione__lte=dateTime) \
& (Q(cancellato__exact=False) | (Q(cancellato__exact=True) & (Q(data_canc__gte=dateTimeC)))))
self.request.session['insolventi_queryset'] = serialize('json', context)
return render(request, self.template_name, {'form':form})
else: return redirect(reverse('insolventi'))
return render(request, self.template_name, {'form':self.form_class()})
this is my template and I am displaying the form manually.
insolventi.html
<form method="get" action="">
{% for field in form %}
{{ field.errors }}
{{ field.as_widget() }}
{% endfor %}
<input type="submit" value="Ricerca" />
</form>
Even if there are errors and form.is_valid() is returning False (giving me a redirect to the same view) on the template I never get {{ form.errors }}.
I don't know what is missing!
I am thinking: Because i use the input of the form to get the query in JSON with django rest and post it on the same template with DataTables, maybe I do not need to use a ListView ??
You should not be redirecting if there are errors since redirecting will lose all the form data.
Try removing the line:
else: return redirect(reverse('insolventi'))
and letting it fall through to the render() line.
Hi can you try this post
custom form validation
also refer django document
django custom validation as per document

Django: Redirect from a form

I'm writing a sports league app. I get a drop down list of all my teams. And I can display the wins/losses data on a separate view. But I can't get the StandingsView (with the form) to correct redirect to the TeamView (display information).
I've tried both POST and GET. I've run into a bunch of issues I don't understand. First, the url from the form is directed to
/teamview/?team_name=6
I don't understand why that is, even if my view specifies otherwise.
Second, the view doesn't redirect unless I do so in the form action. I think that's a product of the GET function, but I'm not sure. I'm hesitant to use POST because I'm not changing the DB
I've looked into RedirectView, but worry (as always) I'm overcomplicating this.
Thank you much,
Views.py
class StandingsView(FormView):
form_class = SelectTeam
template_name = 'teamsports/standings.html'
model = Teams
success_url = '/teamview/'
def form_valid(self, form):
team = form.cleaned_data['team']
return redirect('teamview', team = team)
def form_invalid(self,form):
HttpResponse ("This didn't work")
def TeamView(request, team):
try:
team = Teams.objects.filter(team=team).values()
except Teams.DoesNotExist:
raise Http404("Team does not exist")
return render(request, 'teamview.html', {'team':team})
urls.py
urlpatterns = [
url(r'^$', views.home, name='home'),
url(r'^admin/', admin.site.urls),
url(r'^standings/$', views.StandingsView.as_view(), name="standings"),
url(r'teamview/(?P<team>[0-9]+)/$', views.TeamView, name="teamview")
forms.py
class SelectTeam(ModelForm):
team_name = forms.ModelChoiceField(queryset=Teams.objects.all(), initial=0)
class Meta:
model = Teams
fields = ['team', 'team_name']
standings.html
<form action= "/teamview/" method="GET">
{{ form }}
<input type="submit" value="Submit" />
{{ form.errors }}
</form>
{% endblock %}