Display documents in a table from MongoDB with Jinja2 HTML - python

I currently try to figure out how to display multiple documents from my MongoDB collection "one by one". My recent code to fetch the data looks like this:
#app.route('/shops', methods=['GET', 'POST'])
#login_required
def certified_shops():
shopdata = col.find({ "go": True})
return render_template("tables.html", shopdata=shopdata)
My HTML Jinja injection like this:
<tr>
<td>
{% for data in shopdata: %}
{{ data.url_name }}
{% endfor %}
</td>
</tr>
The code itself works fine - but literally all URLs are displayed in one row of course.
Right now I can't find a good way to handle this.
I just tried to displaying the data with a different loop or some "in range", but this doesn't worked so far. Everything i found here or in the documentation for mongodb and jinja didn't went well for me.
Might there be an easy trick with my html handling or the db query to display one url for each td/tr easy and flexible ?
Since the collection will grow, the list should automatically expand in my web application.
Would love to here some ideas since I've been racking my brain for days now without any good solutions and I've been thinking that there must be an easy way and I just can't see it because it's that simple.

Did I understand your question well? This will create a new row for every url_name:
{% for data in shopdata %}
<tr>
<td>
{{ data.url_name }}
</td>
</tr>
{% endfor %}
Notice. No colon (:) used in the jinja for loop after 'shopdata'.

Related

Python & Flask HTML - Making n number of textboxes based on variable

I have a flask webpage I am trying to create. When users register for an account, they declare the number of agricultural fields they have. This is saved in a MySQL database. From this, I need users to add information on another input page. This input page should have "n" number of textboxes based on the number of fields they have.
Is there anyway to create "n" number of textboxes in HTML? I can read in the number of fields from their account but cannot find a way to create a variable number of textboxes within HTML.
I do not need this to be dynamic (the user add or remove) this needs to be a FIXED amount of textboxes.
I'm going to assume that because of flask you are using jina2 as your rendering engine, let's call the number of fields that need to be created n, you can just use the loop structure
{% for i in range(n) %}
<input name="field-{{i}}" />
{% endfor %}
you can get more info at https://jinja.palletsprojects.com/en/3.0.x/templates/#for
if you need more complex forms, I would recommend using WTForms.
Found a solution, it is a little ugly but should work.
in your html:
<table>
{% for x in range(fields | int) %}
<tr>
<td>
<input type="text" value="{{ x }}">
</td>
</tr>
{% endfor %}
</table>
in python:
def irrigation_input():
...... non important stuff here.....
fields=account_info_irr[9]
int(float(fields))
return render_template('irrigationinput.html',fields=fields)

save dictionary to database from html template in flask

I will try my best to be as concise as possible.
In my back end, I have a list of dictionaries saved to a variable. Each dictionary represents a post from reddit and includes the score, url, and title.
Respectively, the template will loop through this list and then return the values of each of these keys to the user like so:
<table>
<tr>
{% for x in data[0:5] %}
<td>
{{ x['score'] }}
{{ x['title'] }}
<br>
<a href='/add_to_favorites'> Add To Favorites </a>
</td>
{% endfor %}
</tr>
</table>
As you can see, there's an tag which is linked to a function on my utils.py that is attempting to save the respective dictionary to the database (I have a model that represents the url, title, and score).
I feel as though my template is not representing the dictionary in the correct way, for my link to include the html as when it is pressed I receive a 404 error (though I have this route already defined in views.py - '/add_to_favorites' which calls my 'save_post' function).
def save_post():
data = get_info()
for post in data:
fav= Favorite(title=post.get('title'), url=post.get('url'), score=post.get('score'), user_id=current_user.id)
db.session.add(fav)
db.session.commit()
return redirect(url_for('favorites'))
and:
#app.route('/add_to_favorites')
#login_required
def add_to_favorites():
return save_post()
Am i going about this the wrong way? How can i make sure that the link/button is associated with only the html of the that it is included in?
Just need some guidance into the right direction here, not necessarily the code to fix it. Thank you

Updating Jinja2 Variables every X seconds - Python Flask

I am trying to update variables inside of my index.html file. I am going to be running a thread with a loop in python but I want a way to update my jinja2 table listed below to update every x seconds just like if you were using php and ajax.
Here is my Jinja2 Code:
<table border=1 id="allTable" class="display">
<tbody id="eliteTable">
<tr><td colspan=9 class=queueheader>Elite (Current SLA: {{ eliteSLA | safe}}%)</td></tr>
<tr><th>Skill</th><th>SLA</th><th>Calls Waiting</th><th>Hold Time</th><th>Staffed</th><th>Avail</th><th>ACW</th><th>Aux</th><th>ACD Calls</th></tr>
{% for row in eliteList %}
{% if row[2]|int > 30 %}
<tr class=longwait>
{% elif row[2]|int > 0 %}
<tr class=waiting>
{% else %}
<tr>
{% endif %}
{% for i in row %}
<td> {{ i | safe }} </td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
You'll need some javascript in there.
Either ajax requests, or websockets, though ajax might be simpler.
Simply use javascript setInterval() with an ajax request.
I'd recommend using a library, maybe jquery as it is very simple.
$.get( "/auto_refresh", function( data ) {
alert( "Data Loaded: " + data );
});
Note that jinja2 is just for the templating, meaning that at some point the jinja templates get translated into html/css.
So you can play with ajax like you did when you were using PHP.
Jinja variables are generated at template render-time. There's no way to programmatically update them without using javascript of some sort.
From the docs (emphasis mine):
A [Jinja] template contains variables and/or expressions, which get replaced with values when a template is rendered; and tags, which control the logic of the template. The template syntax is heavily inspired by Django and Python.

django-table2 multi-column sorting UI

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.

how can I display models data in django

I am new to django,
I've got models with data that I want to display in a table format.
I'm used to using gridviews in asp.net and I am looking for an alternative.
Is the best way to do this using template iteration tags and is there some sort of tutorials online showing examples on how to do this?
Django explicitly avoids providing front end widgets (like ASP.NET gridviews or Rails scaffolding).
If you want this in a regular template you gotta roll your own:
{% if list %}
<table>
<tr>
<th> Foo </th>
<th> Bar </th>
</tr>
{% for item in list %}
<td>{{item.foo}}</td>
<td>{{item.bar}}</td>
{% empty %}
<td colspan="2">No items.</td>
{% endfor %}
</table>
{% endif %}
However if you want to provide admins with quick ways to edit/view data you can use the Django Admin Site. Make sure you have the django.contrib.admin in your INSTALLED_APPS setting and then (in the most trivial example) just create a admin.py for your app with:
from django.contrib import admin
from myproject.myapp.models import Author
admin.site.register(Author)

Categories

Resources