so i've got this long query here:
showings = db.execute("SELECT showings.cinema_id, showings.movie_id,\
cinemas.name, movies.name FROM showings JOIN\
cinemas ON showings.cinema_id=cinemas.id JOIN\
movies ON showings.movie_id=movies.id WHERE\
showings.id = :id",
{"id": cinema_id}).fetchall()
return render_template("showings.html", showings2=showings2)
and then in the template:
{% for showing in showings2 %}
<option value="{{ showing.id }}">
{{ showing.name }} #{{ showing.name }}
</option>
{% endfor %}
Issue being that due to same column names in two different tables, current template gives back same content twice, that is the value of cinema.name
Any option to bypass it ?
Rename the columns using aliases:
showings = db.execute(
"""SELECT showings.cinema_id
, showings.movie_id
, cinemas.name AS cinema_name
, movies.name AS movie_name
FROM showings
JOIN cinemas ON showings.cinema_id=cinemas.id
JOIN movies ON showings.movie_id=movies.id
WHERE showings.id = :id""", {"id": cinema_id}).fetchall()
and use said aliases in the template:
<option value="{{ showing.id }}">
{{ showing.cinema_name }} # {{ showing.movie_name }}
</option>
Related
i selected a country from a screener function, send this form again to screener function
screenshot
The problem, my form don't keep the last selected country in my form (the variable "country" is send ). I always have the value 'Any' in the form
my list for select
example i
id=1 => 'France'
id=2 => 'Japan'... so if a choose Japan, (id=2) [2]i want to see Japan and not "Any" in the form
[enter image description here]
your help would be appreciated
thank you
screener.html
<form method=POST action="{{ url_for('screener') }}" onchange=submit()>
<table class="table table-sm table-hover">
<thead>
<tr><td>control : {{ country }}</td></tr>
<tr>
<td>Country</td>
<td>
<select id="country" name="country" class="form-select form-select-sm" aria-label="">
<option value="">Any</option>
{% for db_country in db_countries %}
<option value="{{ db_country.id }}" {% if country == db_country.id %} selected {% endif %} >
{{ db_country.id }} - {{ db_country.name }}`</option>
{% endfor %}
</select>
</td>
</tr>
<tr>
</table>
</form>
app.py
`#app.route('/screener/', methods=['POST', 'GET'])
def screener():
db_countries = Country.query.order_by(Country.name.asc()).all()
if request.method == 'POST':
country = request.form['country']
else:
country = 0
return render_template('screener.html', title='Screener',db_countries=db_countries, country=country)`
You are comparing a str to an int. For this reason, the comparison fails.
Change the variable country to an int and it works.
Either you change the type in the endpoint
country = request.form.get('country', 0, type=int)
or in the template.
{% if country | int == db_country.id %} selected {% endif %}
I have got a filter on my page, that filters my items by the category. You can choose the category from a drop-down list and then press search and the filtered content is displayed. The only problem is that, the drop-down list resets and doesn't show the category, that the current items are filtered by. Anyone knows how to solve this?
views.py
def HomeView(request):
item_list = Item.objects.all()
item_list = item_list.annotate(
current_price=Coalesce('discount_price', 'price'))
category_list = Category.objects.all()
query = request.GET.get('q')
if query:
item_list = item_list.filter(title__icontains=query)
cat = request.GET.get('cat')
if cat:
item_list = item_list.filter(category__pk=cat)
price_from = request.GET.get('price_from')
price_to = request.GET.get('price_to')
if price_from:
item_list = item_list.filter(current_price__gte=price_from)
if price_to:
item_list = item_list.filter(current_price__lte=price_to)
paginator = Paginator(item_list, 10)
page = request.GET.get('page')
try:
items = paginator.page(page)
except PageNotAnInteger:
items = paginator.page(1)
except EmptyPage:
items = paginator.page(paginator.num_pages)
context = {
'items': items,
'category': category_list
}
return render(request, "home.html", context)
html:
<form method="GET" action=".">
<div class="form-group col-md-4">
<label for="category">Category</label>
<select id="cat" class="form-control" name="cat">
<option value="" selected>Choose...</option>
<option value="" href="/home">All</option>
{% for cat in category %}
<option value="{{ cat.pk }}">
{{ cat }}</option>
{% endfor %}
</select>
</div>
<button type="submit" class="btn btn-primary">Search</button>
</form>
In template you can add selected attribute to value from request.GET.cat:
<option value="" {% if not request.GET.cat %} selected {% endif %}>Choose...</option>
{% for cat in category %}
<option value="{{ cat.pk }}" {% if request.GET.cat == cat.pk|slugify %} selected {% endif %}>
{{ cat }}
</option>
{% endfor %}
Try setting the value of your dropdown to what the user selects.
For example: If I selected 'Cats' then update your dropdown's default value to 'Cats'.
Basically just keep updating the default value of your dropdown and then check against that.
Hope that helps! :)
I am trying to fill a dropbox with values from my database using Django and HTML. I have been trying to figure out how for hours but it is not updating.
Here is the HTML code:
<select id = "classChoice" >
<option value = "base"> ----- </option>
{% for class.name in objectlist %}
<option value = "class.name"> {{ class.name }} </option>
{% endfor %}
</select>
Here is the forms.py:
class searchPageForm(forms.Form):
className = forms.ModelChoiceField(queryset= Classroom.objects.all())
studentName = forms.CharField(max_length=120)
studentID = forms.CharField(max_length=20)
Here is the views.py:
def search(request):
form = searchPageForm()
if request.GET.get('class.name'):
featured_filter = request.GET.get('class.name')
objectlist = searchPageForm.objects.all()
return render(request, 'pollingSite/search.html', {'objectlist': objectlist})
else:
classNames = Classroom.objects.filter(instructor = request.user)
return render(request, 'pollingSite/search.html', locals())
I am stuck and have tried everything and it's just not populating.
In your html page, the {% for object in objectlist %} means that it will iterate over the objectlist and assign each object in the list to object. This means that you can access the attributes of Classroom using the instance object. So change the html as follows:
<select id="classChoice">
<option value = "base"> ----- </option>
{% for object in objectlist %} <!-- You were making mistake here -->
<option value = "{{ object.id }}"> {{ object.name }} </option>
{% endfor %}
</select>
And in your forms.py:
class searchPageForm(forms.Form):
className = forms.CharField(max_length=120)
studentName = forms.CharField(max_length=120)
studentID = forms.CharField(max_length=20)
I'm trying to show my dictionary keys and values in template in for loop, but I don't want to show the first key.
What is the best way to do it?
I thought of using something like
dictionary.keys()[0]
but i can't do it in template.
or maybe add counter to the for loop (not sure how to do it in the loop below)
This is my loop to show the dictionary-
{% for year, durations in durationDict.items %}
<optgroup label={{ year }}>
{% for duration in durations %}
<option data-from-date="{{ duration.from_date }}" data-to-date="{{ duration.to_date }}" value={{ duration.duration_id }}>{{ duration.from_date }}
- {{ duration.to_date }}</option>
{% endfor %}
{% endfor %}
If you don't want to show the first iteration of a for loop in a Django template, you can omit it by checking for forloop.first
{% for year, durations in durationDict.items %}
{% if not forloop.first %}
<optgroup label={{ year }}>
{% for duration in durations %}
<option data-from-date="{{ duration.from_date }}" data-to-date="{{ duration.to_date }}" value={{ duration.duration_id }}>{{ duration.from_date }}
- {{ duration.to_date }}</option>
{% endfor %}
{% endif %}
{% endfor %}
What I finally done was as following:
creating an OrderedDict out of my Dictionary, making sure that it's sorted by dates Descending:
duration_dict = OrderedDict(sorted(duration_dict.items(), key=lambda t: t[0], reverse=True))
So now I can be sure that the first key is also the latest year.
and for presenting all the key,value pairs without the first year I used forloop.first, as suggested by #bozdoz:
{% for year, durations in duration_dict.items %}
{% if not forloop.first %}
<optgroup label={{ year }}>
{% endif %}
{% for duration in durations %}
<option data-from-date="{{ duration.from_date }}" data-to-date="{{ duration.to_date }}" value={{ duration.duration_id }}>{{ duration.from_date }}
- {{ duration.to_date }}</option>
{% endfor %}
{% endfor %}
You can use a filter tag. For example:
template_tags.py
from django import template
register = template.Library()
#register.filter()
def exclude_first(dict):
first_key = list(dict)[0]
del dict[first_key]
return dict
html
{% load template_tags %}
{% for year, durations in durationDict|exclude_first %}
...
{% endfor %}
This should allow you to loop through all of the items in durationDict except for the first item. Keep in mind that dicts are not ordered by default. If you have a custom key/value pair that you want deleted every time, you can simply replace del dict[first_key] with del dict['latest_year'] (or replace latest_year with the key name you want to delete).
I have an html template that includes some Python code and HTML templates. This is a sample below.
Python:
cur1 = g.db.execute('select ID from Students')
students = [dict(ID=row[0]) for row in cur1.fetchall()]
cur2 = g.db.execute('select ID from Quizzes')
quizzes = [dict(ID=row[0]) for row in cur2.fetchall()]
if request.method == 'POST':
if not session.get('logged_in'):
abort(401)
g.db.execute('insert into Results (quiz,student,grade) values '\
'(?,?,?)',[request.form['Quiz'],
request.form['Student'],
request.form['grade']])
g.db.commit()
return render_template('add_result.html',students=students,quizzes=quizzes)
HTML:
<form action="{{ url_for('add_result') }}" method=post>
<select name="Quiz">
{% for quiz in quizzes %}
<option value="{{ quiz }}">{{ quiz.ID }}</option>
{% endfor %}
</select>
<select name="Student">
{% for student in students %}
<option value="{{ student }}">{{ student.ID }}</option>
{% endfor %}
</select>
<input type="number" name="grade">
<input type="submit" value=Submit>
</form>
which outputs the drop down lists in the format I want (integers), however, for example, say the values quiz #1 and student #1 with a grade of 100, they are then input into SQLite as
(2, u"{'ID': 1}", u"{'ID': 1}", 100.0)
How can I get this output?:
(2,1,1,100.0)
You need to convert the values to the right type before sending them to the database. The request.form dict provides a get method that will convert values or raises an error.
g.db.execute(
'insert into Results (quiz,student,grade) values (?,?,?)',
(
request.form.get('Quiz', type=int),
request.form.get('Student', type=int),
request.form.get('grade', type=float)
)
)
It would be much easier (and safer) in the long run to use a form library such as Flask-WTF to parse, convert, and validate the data for you. Also consider using an ORM such as Flask-SQLAlchemy rather than writing raw SQL statements.
The problem was in the HTML:
<select name="Quiz">
{% for quiz in quizzes %}
<option value="{{ quiz }}">{{ quiz.ID }}</option>
{% endfor %}
</select>
<select name="Student">
{% for student in students %}
<option value="{{ student }}">{{ student.ID }}</option>
{% endfor %}
I had "quiz" and "student" as the s, with quiz.ID and student.ID appearing as text in the values. It is the option value that gets returned by the form.
It should be:
<select name="Quiz">
{% for quiz in quizzes %}
<option value="{{ quiz.ID }}">{{ quiz.ID }}</option>
{% endfor %}
</select>
<select name="Student">
{% for student in students %}
<option value="{{ student.ID }}">{{ student.ID }}</option>
{% endfor %}