I have a for loop created with jinja2 on my html, showing a list of users in my sqlite database:
{% for user in users %}
<tr>
<td>{{ user.id }}</td>
<td>{{ user.username }}</td>
<td>{{ user.email }}</td>
<td>
{% if user.admin == True: %}
Admin Icon
{% else: %}
Not Admin Icon
{% endif %}
</td>
</tr>
{% endfor %}
I would like to know how can I pick the specific user from the line the link is clicked?
I tried to catch it through url_for:
Admin Icon
But I got this message on terminal:
jinja2.exceptions.TemplateSyntaxError: expected token ',', got 'string'
I don't know what is the more appropriated way to do this.
I think this might be because of a syntax error rather than anything to do with your loops. You seem to have an extra double quote in your url_for arguments: user=user" should be user=user. This extra quotation mark has the undesired effect of closing the value of the href attribute which also starts with a double quote, leaving the closing brackets and braces outside of the attribute. Your <a> tag should look like this:
Admin Icon
It is generally considered best practice to use double quotes in HTML attribute values, so use single quotes when inserting strings with Jinja for arguments.
Related
I am following this video and everything is working perfectly. The output of a SQL query is saved within a variable that I can call on in another .html page.
so my sql query is:
#app.route('/all_data')
def all_data():
customers = db.get_customers()
for customer in customers:
var = customers
return render_template('all_data.html',var=var)
When calling this {{var}} in all_data.html page the output is for a long tuple:
('name','email','comment','gender'),('name','email','comment','gender') etc etc
I am looking to put this {{var}} into a table instead?.. I but am hitting a brick wall in finding out how to do this?
any help would be much appreciated!
Assuming you're using Flask's default template engine (Jinja2), you can simple use a for loop to iterate over the elements of the collection inside the template. The syntax is:
{% for item in items %}
{{ item }}
{% endfor %}
So simply create an HTML table, and add a row for each item in your var variable.
IIRC, Jinja tuples act the same as Python's, so you can probably do something along the lines of:
<table>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Comment</th>
<th>Gender</th>
</tr>
</thead>
<tbody>
{% for current in var %}
<tr>
<td>{{ current[0] }}</td>
<td>{{ current[1] }}</td>
<td>{{ current[2] }}</td>
<td>{{ current[3] }}</td>
</tr>
{% endfor %}
</tbody>
</table>
I haven't checked it (as I don't have a Flask project available right now), but if my memory serves me right, that's how I would do it
Here's a link to an usefull part of Jinja2's documentation
Also, what is this piece of code for ?
for customer in customers:
var = customers
You're iterating over each element of the list, but your never use the customer variable (containing the current element). Instead, you assign the var variable to the customers list multiple times. Assuming customers is a simple Python list, you could remove this loop and simply do return render_template('all_data.html',var=customers)
I am building a Flask application to manage character sheets for an RPG using an SQL database.
Currently, I have the following script that displays the list of a user's characters currently in the database.
#app.route("/<cha_name>")
#login_required
def character_sheet():
characters = db.execute(
"""SELECT
*
FROM
characters
WHERE
user_id = :user_id AND
name = :cha_name
""",
user_id=session["user_id"],
cha_name="???",
)
if not characters:
return render_template("add_char.html")
I would like to include a button that navigates to the character sheet for the specic chosen character. So the page below would detail some of the stats for the character, and then a button would take the user to a populated character sheet on another page.
This is what I have so far for displaying a specific user's characters.
{% extends "main.html" %}
{% block title %}
Characters
{% endblock %}
{% block main %}
<table border = 1>
<thead>
<td>Player</td>
<td>Name</td>
<td>Race</td>
<td>Class</td>
<td>Level</td>
<td>Status</td>
<td>View</td>
</thead>
{% for row in rows %}
<tr>
<td>{{ character["user"] }}</td>
<td>{{ character["name"] }}</td>
<td>{{ character["race"] }}</td>
<td>{{ character["cha_class"] }}</td>
<td>{{ character["level"] }}</td>
<td>{{ character["status"] }}</td>
<td><a href={{ url_for('cha_name') }}>View Sheet</a></td> <!-- HERE -->
</tr>
{% endfor %}
</table>
Add a new Character
Go back to home page
</body>
{% endblock %}
What do I use on the line with <!-- HERE --> to make a link to the character sheet URL?
Whew, there's a lot to unpack here!
Your example is/was invalid, e.g. cha_name= on the end of the db.execute() call, and there are no calls to render_template if a character is found, so it'll never produce a response even with a valid request.
Next, you've told Flask to pass a cha_name parameter to your character_sheet function, but haven't defined a parameter on the function itself.
Finally, in your template you're passing cha_name to the url_for function, which (so far as we can see from the sample code) isn't a route that you've defined, so can't work.
You need to include more information for us to help, such as telling us what error you're seeing. Right now, I imagine the Flask service won't even start due to the syntax error. Once that's fixed, I'd expect to see something like the following:
werkzeug.routing.BuildError: Could not build url for endpoint 'cha_name'. Did you mean 'character_sheet' instead?
I'd suggest you head back to the documentation on URL building and also look at the docs for the route decorator. You'll see on the latter that "Flask itself assumes the name of the view function as endpoint". That means that in order to get Flask to generate a URL for your character_sheet function, you'll need to pass that name to url_for, and then the parameters, like this:
url_for('character_sheet', cha_name=character.name)
If a user were to rename their character, all of the URLs would change, which is a bad user experience — what would happen if they'd bookmarked a particular character, then fixed a typo in the name?
Putting this all together, here's a hopefully-better example:
# app.py
#login_required
#app.route("/<character_id>")
def character_sheet(character_id):
characters = db.execute(
"""SELECT
*
FROM
characters
WHERE
id = :id AND
user_id = :user_id
""",
id=character_id,
user_id=session["user_id"],
)
if not characters:
return abort(404)
return render_template(
"characters/sheet.html",
character=characters[0],
)
<!-- templates/characters/list.html -->
{% extends "main.html" %}
{% block title %}
Characters
{% endblock %}
{% block main %}
<table>
{% for character in characters %}
<tr>
<td>{{ character.name }}</td>
<td><a href={{ url_for('character_sheet', character_id=character.id) }}>View Sheet</a></td>
</tr>
{% endfor %}
</table>
Add a new Character
{% endblock %}
Hello I have an app that displays some database information in a table. Inside of the html template I am making an edit link that I want to open another app(page viewLit) while passing a value to it's view. I have added my code below. My question is I am unsure of how to make this links url and pass the object data located inside circuit.circuitid along with it. I haven't been able to find the right way to code this yet and this is just how I thought that this should be done. If anyone has a better idea I am open to suggestions.
search_custom.html(code for link)
{% for circuit in filter.qs %}
<tr>
<td class="actions">
View
</td>
<td>{{ circuit.circuitid }}</td>
</tr>
{% endfor %}
myapp/myapp/urls.py
urlpatterns = [
path('viewLit/', include('viewLit.urls')),
]
myapp/viewLit/urls.py
urlpatterns=[
path('viewLit/circuitid.id', views.viewLit, name='viewLit'),
]
myapp/viewLit/views.py
def viewLit(request, circuitid):
#display records fields here
return HttpResponse("You are at the viewLit page!")
Have a look at the documentation:
Django documentation
myapp/viewLit/urls.py
urlpatterns=[
path('viewLit/(?P<circuit_id>\w+)', views.viewLit, name='viewLit'),
]
html- template:
search_custom.html(code for link)
{% for circuit in filter.qs %}
<tr>
<td class="actions">
View
</td>
<td>{{ circuit.circuitid }}</td>
</tr>
{% endfor %}
I am trying to do multi-column sorting in django-tables2.
I can add ?sort=date&sort=job_number
to the end of my url and it will sort by date, then job number.
But when a user clicks a column heading, it will replace the current sort querystring with the new one! Is there a way to more elegantly expose multi-column sort to the end users?
I am using the 'querystring' tag from django-tables2, but as stated above, it rewrites the value instead of appending it.
Okay, I have worked out a solution that works, but it isn't quite perfect, so if anyone wants to propose something better, I'm all ears!
First, I created a new templatetag (see https://docs.djangoproject.com/en/1.8/howto/custom-template-tags/ for details about where to put a custom templatetag)
from django import template
from django_tables2.templatetags.django_tables2 import querystring
register = template.Library()
#register.inclusion_tag('django_tables2/header.html', takes_context=True)
def render_header(context):
for column in context['table'].columns:
column.sort_existing = False
if 'sort' in context['request'].GET:
if column.name in context['request'].GET['sort']:
column.sort_existing = True
return context
Then, I created a custom template called django_tables2/header.html for that tag to use:
{% load querystring from django_tables2 %}
<thead>
<tr>
{% for column in table.columns %}
{% if column.orderable %}
{% if column.sort_existing %}
<th {{ column.attrs.th.as_html }}><a href='{% querystring table.prefixed_order_by_field=column.order_by_alias.next %}'>{{ column.header }}</a></th>
{% else %}
<th {{ column.attrs.th.as_html }}><a href='{% querystring %}&{{ table.prefixed_order_by_field }}={{ column.order_by_alias }}'>{{ column.header }}</a></th>
{% endif %}
{% else %}
<th {{ column.attrs.th.as_html }}>{{ column.header }}</th>
{% endif %}
{% endfor %}
</tr>
</thead>
And Finally, I altered my django_tables2/table.html template to use my custom templatetag to render the table header, replace the table.thead block with:
{% block table.thead %}
{% render_header %}
{% endblock table.thead %}
And that should do the trick! Clicking on multiple column headers will sort them in the order clicked, clicking on a the same one twice will clear previous selections (and reverse the order). It isn't perfect. Perhaps I'll improve upon it later, but it works for my immediate use case.
Perhaps I will reach out to the django_tables2 project to see if they are interested in including my custom template tag into the main project :)
EDIT: I should note, this requires 'django.core.context_processors.request' or equivalent in your context processors in your settings.
EDIT: Fixed table.html to correct code. Also, see https://github.com/bradleyayers/django-tables2/issues/223 to track this issue.
It looks like this is not an option for django-tables2 at the moment, though it is noted as an issue on the git page. I would also like to see this as on option for this package as well.
Looking through the source code briefly in the table.html template the href for the column header is produced by the following code: {% querystring table.prefixed_order_by_field=column.order_by_alias.next %}. Digging a little deeper it appears that there is an OrderByTuple object, that seems to want to perform this function, but never gets passed to the rendering. I haven't dug down enough to figure out why this OrderByTuple is not passed to the href, but may have something to do with the fact the the OrderBy called from the template referenced above is linked to the column and not the table. Sorry I couldn't acutually come up with a solution, but hope this helps a little.
I have a template which has a code like
<td>{{ contact.Tag_ID }}</td>
to list the Tag_ID of items in a table. Now when I click on ot it goes to as os page which is a form with the Tag_ID field. I some how want to catch the Tag_ID when I click on it and pass it to the view ans set it as the initial value. I know how to set the initial value but cannot figure how to catch the Tag_ID or its associated data.
A simple solution would be to pass the value in the url:
<td>{{ contact.Tag_ID }}</td>
or
<td>{{ contact.Tag_ID }}</td>
In the second case, it is just an old-style query string, which you can use javascript to read. But, the better (django) way would be to use the first method, and do a pretty url.
In urls.py:
(r'^os/(?P<tag_id>[a-zA-Z0-9]*)/*', 'os_view_handler'),
Then in views.py:
def os_view_handler(request, tag_id=None):
...
url code:
<a class="item" href="{% url "your_views_funct" contact.Tag_ID %}">{{ contact.Tag_ID }}</a>
and add this to your urls.py:
(r'^os/(?P<tag_id>[a-zA-Z0-9]*)/*', 'your_views_funct'),
Without knowing too much about your app, I'm guessing you want a URL like /os/<ID>/
First of all, you should declare this URL in your app's url.py. Second of all, use the {% url %} tag in the template. https://docs.djangoproject.com/en/dev/ref/templates/builtins/ And thirdly, your view should be able to accept this ID as a parameter and act accordingly.