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
Related
I am trying to extend the UserCreationForm using a Bootstrap layout style for the field username. After the input tag in the registration form, I would like to add a div element like an example that I have readapted from the Bootstrap page: i.e. suggesting the user to enter the same username as the company domain.
Let's focus to the bare minimum. The form readapted from Bootstrap is:
<form class="row gy-2 gx-3 align-items-center method="POST" action="{% url 'register' %} ">
<div class="col-auto">
<div class="input-group">
<input type="text" name="username" class="form-control" placeholder="your.username" id="id_username">
<div class="input-group-text">#company.domain.com</div>
</div>
</div>
<div class="col-auto">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
Which produces the following:
For the moment, I am using only {{form.as_p}} in my html template file:
<form class="row gy-2 gx-3 align-items-center method="POST" action="{% url 'register' %} ">
{{form.as_p}}
<div class="col-auto">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
And I don't know how to add the <div class="input-group-text">#company.domain.com</div> part embedded in a <div class="input-group">...</div> block.
My actual forms.py is a bit more complex, but readapted for this minimum example it contains the widget attributes as follows:
class SignupForm(UserCreationForm):
username = forms.CharField(label="",
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'your.username'}))
class Meta:
model = User
fields = (
'username',
)
Without additional libraries, is there a way to extend the widget attributes? Is it even possible to use {{form.as_p}} as I am currently doing or should I use another method?
If you want to use only {{ form.as_p }} with bootstrap then you need to install django-bootstrap.
Install it using pip:
pip install django-bootstrap4
After installation, add it in INSTALLED_APPS in settings.py file.
INSTALLED_APPS = [
'bootstrap4',
]
And in templates, you need to load it.
{% load bootstrap4 %}
{% bootstrap_messages %}
<form class="row gy-2 gx-3 align-items-center method="POST" action="{% url 'register' %} ">
{% csrf_token %}
{% bootstrap_form form %} # added `form` here. we don't need to use with as_p.
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
This is the way you can use bootstrap along with {{ form.as_p }}
OR
Try another way:
Simply you can use {{ form.username }} inside an input tag in template.
For Example:
<input type="text" value="{{ form.username }}">
<form class="row gy-2 gx-3 align-items-center method="POST" action="{% url 'register' %} ">
<div class="col-auto">
<div class="input-group">
<input type="text" name="username" class="form-control" placeholder="your.username" id="id_username" value="{{ form.username }}"> #Added here
<div class="input-group-text">#company.domain.com</div>
</div>
</div>
<div class="col-auto">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
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 }}
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?
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.
I'm trying POST my text value from my HTML form to Django view but always get NONE as a result.
Initially, I was trying to fetch value by request.POST which threw "MultiValueDictKeyError" then I changed my code to request.POST.get which is returning None
HTML file
{% csrf_token %}
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1" style="margin-top: 5px">
<ul class="nav navbar-nav">
<li class="dropdown" style="padding-right: 10px">
<select class="form-control" id="sel1" style="font-family: Courier">
{% for environment in env_list %}
<option name="NewEnvName"
value="{{ environment.Env_name }}">{{ environment.Env_name }}</option>
{% endfor %}
</select>
</li>
</ul>
<ul class="nav navbar-nav">
<li class="dropdown" style="font-family: Courier;font-size: 20px;color: ivory">
<input type='radio' name='CobranSelection' value="CobrandName" checked/>
<label for="edit-radios-lorem-tortor-erat" class="option"
>Cobrand
Name | </label>
<input type='radio' name='CobranSelection' value="CobrandId"/>
<label for="edit-radios-lorem-tortor-erat" class="option"
>Cobrand
Id </label>
</li>
</ul>
<div class="form-group">
<input type="text"
style="margin-top: -1px;font-family: Courier;width: 210px;margin-right: -10px"
class="form-control"
name="cobrand" placeholder="Eneter Cobrand detail here">
<button type="submit" class="btn btn-default"
style="margin-top: -31px;font-family: Courier;margin-left: 230px">
Submit
</button>
</div>
</div><!-- /.navbar-collapse -->
</form>
view.py
from django.shortcuts import render, HttpResponseRedirect
from .models import Environments
from django.db.models import Q
import cx_Oracle
def knowcobrand(request):
value_type = request.POST.get('CobranSelection')
cobrand_value = request.POST.get('cobrand')
env = request.POST.get('NewEnvName')
print(value_type)
print(cobrand_value)
print(env)
return render(request, 'CobrandView/CobrandInDepth.html')
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url('login', views.login),
url('Home', views.fetch_all_env),
url('AddEnvironment', views.add_environment),
url('GetEnvironment', views.GetEnvironment),
url('ReadDb', views.readdb),
url('LearnCobrand', views.learncobrand),
url('ReadCobrand',views.knowcobrand)
]
I'm posting my HTML and views.py for reference. Could anyone of you please help me by pointing out my mistake.
add this attribute to your form :
enctype="multipart/form-data"
like this :
<form action="" method="post" enctype="multipart/form-data">
and attention in view side file field use request.FILES