Django Forms not showing - python

I am trying to use Django provided forms instead of manually creating them with HTML. When I do this, however, they do not appear. The questions/answers I have found on this site have so far been unable to solve my issue. (unless I am reading them wrong.)
forms.py
from django import forms
class KeywordForm(forms.Form):
input_keywords = forms.CharField(label="Keywords", max_length='100')
class LocationForm(forms.Form):
input_location = forms.CharField(label="Location", max_length="250")
views.py
from django.shortcuts import render
from .forms import KeywordForm, LocationForm
def search_view(request):
keyword_form = KeywordForm()
location_form = LocationForm()
return render(request, 'search_results.html', {'keyword_form': keyword_form, 'location_form': location_form})
urls.py
from django.urls import path
from . import views
urlpatterns = [
...
path('search/', views.search_view, name='search'),
]
base.html
{% block search %}
<div class="card">
<div class="card-body">
<form class="row align-items-center">
<form action="search" method="GET">
<div class="col-sm-2">
{{ keyword_form }}
</div>
<div class="col-sm-2">
{{ location_form }}
</div>
<!-- <label for="inputKeywords" class="form-label">Keywords</label>-->
<!-- <input class="form-control" id="inputKeywords" type="text" name="inputKeywords" placeholder="Enter Keywords...">-->
<!-- </div>-->
<!-- <div class="col-sm-2">-->
<!-- <label for="inputLocation" class="form-label">Location</label>-->
<!-- <input type="Text" class="form-control" id="inputLocation" name="inputLocation" placeholder="Enter location...">-->
<!-- </div>-->
<div class="col">
<input class="btn btn-primary" type="submit" value="Search">
</div>
</form>
</form>
</div>
</div>
{% endblock %}
Per request: search_results.html, which isn't finished due to the forms not showing up in base.html.
{% extends 'base.html' %}
{% block search %}
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="navbar-nav">
<form action="search" method="GET">
{{ keyword_form }}
{{ location_form }}
<input class="btn btn-primary" type="submit" value="Search">
</form>
</div>
</nav>
{% endblock %}

In base.html replace this:
{% block search %}
<div class="card">
<div class="card-body">
<form class="row align-items-center">
<form action="search" method="GET">
<div class="col-sm-2">
{{ keyword_form }}
</div>
<div class="col-sm-2">
{{ location_form }}
</div>
<div class="col">
<input class="btn btn-primary" type="submit" value="Search">
</div>
</form>
</form>
</div>
</div>
{% endblock %}
with this:
{% block search %}
{% endblock search %}
Let me see if i can explain clearly what's happening here..
You created a view for search_results.html so when you render that page the view passes the context variable to it, which includes the forms. All good 'till here.
From the code you shared i see that then you went ahead and added the Django Template Language to render those forms directly in base.html. But that won't work because base.html doesn't have access to the context variable you're passing to search_results.html.
When you extend a template and you add content within blocks that are present in the parent template, what happens is that the block in question is overwritten.
So in your case, whatever you're writing between search blocks in base.html will be wholly overwritten by what's in between those same blocks in search_results.html.
From what i see there are no errors in the code so I think all you have to do is to work on your search_results.html template. And when you test if it works or not do so on search_results.html, not anywhere else, because that's the template that will have access to the context dictionary.
The problem might also be that for some reason those form elements are empty, or that something is wrong at some other step of the way. The template doesn't mind being passed empty context variables so you should also consider that maybe the forms are being passed to the template but they're just empty. You have to run little tests for these things. Try passing a variable containing a simple string to the template and try to render that. Does it work? Good, at least you know that the problem is somewhere else. Doesn't it? Even better, you're one step closer to the solution.

Related

Problems to display the Form in the Template using CreateView

What happens is that I am using CreateView and I find it curious that the code works when I put {{form}}, it displays all the fields and saves in the database (everything works very well) but when I break down the values ​​one by one for example: {{form.plates}}, {{form.type}}, it does not send anything to the database and it stays on the same page. Why is that? I just need it broken down
clientes-add.html
<form enctype="multipart/form-data" method="post">
{% csrf_token %}
<div class="row mb-3">
<div class="col-md-3">
<div class="mb-3">
<label>Customer type</label>
<br>
<div class="form-check form-check-inline">
{{ form.tipo }}
</div>
</div>
</div>
</div>
<div class="row mb-3 only-corp hide-item">
<div class="col-md-12">
<div class="mb-3">
<label>Corporation name</label>
{{ form.corporacion }}
</div>
</div>
</div>
<button class="btn btn-primary mb-3" type="submit" value="Post">Save</button>
</form>
You also need to render {{form.fieldname.errors}} for each {{form.fieldname}}. The error will be telling you why the form is not valid, but you cannot see them!
You can test it if there is extra html you want to generate only if there are errors.
{% if form.fieldname.errors %} <br> {{form.fieldname.errors }} {% endif %}
Don't forget {{form.non_field_errors }}

Django multiple radio input from HTML form with same name

I am having a problem with Django forms. I am currently using the request.POST to validate the POST within views.
I want to send inputed-data(radio type) from my template with the same name.
In my template.py:
<form method="post" action="{% url 'app:AnsSubmission' %}">
{% csrf_token %}
{% for i in Exam %}
<div class="form-group col-xl-12">
<label>{{ i.question }}</label>
<div class="radio">
<label><input type="radio" class="mx-2" name="givenAns" array_column="{{ i.pk }} value="True" required>True</label>
</div>
<div class="radio">
<label><input type="radio" class="mx-2" name="givenAns" array_column="{{ i.pk }} value="False" required>False</label>
</div>
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
And willing to fetch these data in views.py like:
givenAns_list = request.POST.getlist('givenAns')
for i in givenAns_list:
this_givenAns = givenAns_list[i]
But the problem here is this radio type input field doesn't take value for the same name(not as a list I wish). If I select answer of 2nd question, the 1st one's selection is unselected.
Please suggest how can I fix this?

Using App name with Django.contrib.auth views

I am new to Django and I am creating a user change password page. However, I keep encountering a NoReverseMatch error which I suspect is due to my app name but I am not able to resolve it even after spending hours googling for a solution.
My urls.py file:
from os import name
from django.urls import path
from account import views
from django.contrib.auth import views as auth_views # Import Django built-in authentication views
app_name = 'account'
urlpatterns = [
path('test/', views.test_login, name='test'),
path('login/', auth_views.LoginView.as_view(), name='login'),
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
path('password_change/done/', auth_views.PasswordChangeDoneView.as_view(), name='password_change_done'),
path('password_change/', auth_views.PasswordChangeView.as_view(), name='password_change'),
]
My settings.py:
# Login Logic
LOGIN_REDIRECT_URL = 'account:test' # Tells Django which URL to redirect user to after a successful login if no next parameter is present in the request
LOGIN_URL = 'account:login' # The URL to redirect the user to log in - based on the name in the urls.py
LOGOUT_URL = 'account:logout' # The URL to redirect the user to log out - based on the name in the urls.py
my html file
{% extends "base.html" %}
{# This is the template to allow user to change their password #}
{% block title %}Change Your Password{% endblock title %}
{% block content %}
<div class="container">
<div class="row justify-content-center">
<div class="col-8">
<form action="{% url 'account:password_change_done' %}" class="form-signin" method="post">
{% csrf_token %}
<h1 class="h3 mb-3 font-weight-normal text-center">Change your password</h1>
<div class="form-group">
<label for="old_password">Old Password</label>
<input class="form-control" type="password" required id="id_old_password" name="old_password" autocomplete="current-password" placeholder="Old Password" autofocus>
</div>
<div class="form-group">
<label for="new_password1">New Password</label>
<input class="form-control" type="password" required id="id_new_password1" name="new_password1" autocomplete="new-password" placeholder="New Password">
</div>
<div class="form-group">
<label for="new_password2">Confirm Password</label>
<input class="form-control" type="password" required id="id_new_password2" name="new_password2" autocomplete="new-password" placeholder="Confirm Password">
</div>
<small class="form-text text-muted">
{% if form.new_password1.help_text %}
{{ form.new_password1.help_text|safe }}
{% endif %}
</small>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
</div>
</div>
</div>
{% endblock content %}
Much help is appreciated.
Have added in the html file for referece
A "NoReverseMatch" error means , Django is not being able to process and see the exact url being passed.
Including the "app_name" has said by most Django devs makes the code neat and easy to streamline to as to which url you want and most importantly helps to avoid duplicating urls..
An instance will be having this url path of "home" in your app accounts and also having that same path "home" in some other app, the use of specifying the app_name will help Django , include the urls to their respective apps so you know which requires which .
Your urls are correct to me and since it's a NoReverseMatch error, it will have to be your at your html or view or anywhere where you are calling a url.
Try including the app name in either your html and view on where you are calling the url..
Something like this
{% app_name:name_url %}
And same to the view app_name:name_url
Always make sure there is semi-colon between the app_name and the url ... As it will help you tell Django as to which url from which app!!

Numbered loop in Jinja

I'm trying to make a quiz app using Django, Jinja2 and PostgreSQL. I want to number the questions but I don't know how to because python doesn't use a counter in for loops (e.g. for exercise in exercises - no for loop here)
I've tried to change the for loop
(for exercise in exercises)
so it has a counter
(for x in myrange)
and defining myrange in views.py to be a range(1, len(exercitii+1))
but after that I didn't know how to access the elements inside the Jinja template.
I tried to access the exercises with
{exercitii.x-1.intrebare}}
but it didn't work.
html template
{% extends 'base.html' %}
{% load static %}
{% block content %}
</div>
<div id="middle-section" class="container-fluid container-fluid-margin">
<div class="content-quiz">
<form action="{% url 'exercitiu' lectii.id %}" method="POST" id="quiz">
{% for exercitiu in exercitii %}
<div class="row content-block">
<div class="col-lg-10 text-card">
{% csrf_token %}
<div class="card card-custom">
<div class="card-body">
<h5 class="card-title">{{exercitiu.id}} - {{exercitiu.intrebare}}</h5>
<div class="card-text">
<input type="radio" name="question-{{exercitiu.id}}-answers" id="question-{{exercitiu.id}}-answers-A" value="A" />
<label for="question-{{exercitiu.id}}-answers-A">A) {{exercitiu.variante.0}} </label>
</div>
<div class="card-text">
<input type="radio" name="question-{{exercitiu.id}}-answers" id="question-{{exercitiu.id}}-answers-B" value="B" />
<label for="question-{{exercitiu.id}}-answers-B">B) {{exercitiu.variante.1}} </label>
</div>
<div class="card-text">
<input type="radio" name="question-{{exercitiu.id}}-answers" id="question-{{exercitiu.id}}-answers-C" value="C" />
<label for="question-{{exercitiu.id}}-answers-C">C) {{exercitiu.variante.2}} </label>
</div>
<div class="card-text">
<input type="radio" name="question-{{exercitiu.id}}-answers" id="question-{{exercitiu.id}}-answers-D" value="D" />
<label for="question-{{exercitiu.id}}-answers-D">D) {{exercitiu.variante.3}} </label>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
<input type="submit" value="Trimite" class="btn btn-secondary btn-block btn-login-custom" style="margin-bottom: 2rem;">
</div>
</div>
{% endblock %}
views.py
from django.shortcuts import render
from django.shortcuts import get_object_or_404
from .models import Exercises
from .models import Lectie
def exercitii(req):
lectii = Lectie.objects.all().order_by("id")
context = {
'lectii': lectii
}
return render(req, '../templates/pagini/exercitii-selector.html', context)
def exercitiu(req, lectie_id):
lectii = get_object_or_404(Lectie, pk=lectie_id)
exercitiiObj = Exercises.objects.filter(idLectie=lectie_id)
context = {
'lectii': lectii,
'exercitii': exercitiiObj
}
return render(req, '../templates/pagini/exercitii.html', context)
(lectie = lesson, lectii = lessons, exercitii = exercises)
So how can I number the questions from exercitiiObj in the template? Right now the output is the exercise ID from the DB which isn't helpful at all.
Thanks.
If I got your question correctly, you want to get the iteration number of the for loop in jinja.
Jinja provides a very convenient loop variable, it has a property called loop.counter which is 1-indexed, and loop.counter0 which is 0-indexed. View Docs
And if you're using DjangoTemplate, then those become forloop.counter0 and forloop.counter. View Docs

custom django form template (in bootstrap)

I would like to customize my django forms.
For example, in my code I have working hour settings which I like to produce like this format:
mon_start mon_end
tue_start tue_end
....
but instead it creates a form
mon_start
mon_end
tue_start
tue_end
....
Here is a view of the output that I dont want
Below are my code:
forms.py
class CompanyWorkingHoursSettingsForm(forms.ModelForm):
mon_start = forms.TimeField()
mon_end = forms.TimeField()
tue_start = forms.TimeField()
tue_end = forms.TimeField()
class Meta:
model = Workinghours
fields = ("mon_start","mon_end","tue_start","tue_end")
workinghourssettings.html
{% extends 'project/base.html' %}
{% load bootstrap3 %}
{% block page %}
<div class="col-lg-12">
<div class="panel">
<div class="panel-heading bg-blue">
<h4 class="panel-title text-center text-white">
Working Hours Settings
</h4>
</div>
<div class="panel-body">
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{% bootstrap_form company_workinghourssettings_form %}
<button type="submit" class="btn btn-pink">Update</button>
</form>
</div>
</div>
</div>
{% endblock %}
How do i produce a custom arranged form for my form fields above ? (in bootstrap)
As suggested in the comments you may try rendering your fields one by one, and apply bootstrap grid:
<form>
<div class="row">
<div class="col-md-6">{{ my_form.field_1 }}</div>
<div class="col-md-6"{{ my_form.field_2 }}></div>
</div>
....
</form>
If the problem is with the placeholder you can just use
mon_start =forms.TimeField(label='the label', widget=forms.TextInput(attrs={'placeholder': 'What ever you want here'}))

Categories