I have JSON data that I want to publish on a webpage in a table format. I'm stuck to validate dates in the jinja template as few dates are missing and data needs to be published under those dates only for which data is available.
JSON DATA I HAVE:
https://cdn-api.co-vin.in/api/v2/appointment/sessions/public/calendarByPin?pincode=241301&date=21-05-2021
[PAGE VIEW I WANT][1]
[1]: https://i.stack.imgur.com/OfVnT.png
MY CODE:
<tbody>
{% for center in centers %}
<tr>
<th scope="row">
<address>
{{ center['name'] }} <br>
{{ center['address'] }}
</address>
</th>
{% for date in dates %}
{% if date == center["sessions"][dates.index(date)]["date"] %}
<td>
{{ center["sessions"][dates.index(date)]["available_capacity"] }} <br>
{{ center["sessions"][dates.index(date)]["min_age_limit"] }} <br>
{{ center["sessions"][dates.index(date)]["vaccine"] }} <br>
</td>
{% else %}
<td>None</td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
I have got a solution to this problem. I can preformat data in a new python dictionary rather than direct pushing raw JSON data to the Jinja template, but I'm keener to understand if we can apply any other approach.
You should not add much logic into templates.
There are a few reasons for this:
Best practices. Single responsibility principle.
Good design - application logic independent from the view logic.
Prevent illegible, hard to understand and maintain implementation.
Save your future you from a lot of effort
To be able to do something, especially in a language like Python that allows to mix and go very deep and complex (and even ugly) if you want to, does not mean you should.
Related
I have a setup in SQLAlchemy ORM (using Flask-SQLAlchemy) with Book and BookSubject classes, the latter being a many-to-many relationship (there is, of course, a Subject class, but it's not relevant to this question). I have a working query to return all books based on the date the subject was added to the database (there's a reason for this):
records = Book.query.\
filter(BookSubject.book_id == Book.id).\
filter(BookSubject.subject_id.in_([1, 12, 17])).\
filter(BookSubject.created > '2021-01-01').\
order_by(db.desc(BookSubject.created)).\
paginate(page, 50, True)
I then pass records to a Jinja2 template and do assorted stuff to display it; it works perfectly.
I'd now like to do the obvious thing and actually display the creation date (i.e. BookSubject.created, from the order_by clause), but I can't figure out how to add this to the query. Putting in add_columns((BookSubject.created).label("added")) isn't the answer; that throws an error when I try to use one of the record objects "'sqlalchemy.util._collections.result object' has no attribute 'id'". The template code that generates this is (roughly):
{% for book in records.items %}
<tr><td>{{ book.title }}</td></tr>
{% endfor %}
This should be obvious; how am I meant to add this to the result?
By using add_columns
Book.query.add_columns((BookSubject.created).label("added"))
it will return a named tuple with fields Book and added, so to access book fields you'd need something like book.Book.id
{% for book in records.items %}
<tr><td>
{{ book.Book.title }} {{ book.added }}
</td></tr>
{% endfor %}
or iterate by pairs:
{% for book, added in records.items %}
<tr><td>
{{ book.title }} {{ added }}
</td></tr>
{% endfor %}
If you want a flat structure (and without add_columns), then you can use
session.query(
Book.id,
Book.title,
BookSubject.created.label('added')
).filter(BookSubject.book_id == Book.id)...
then results will have a named tuple with fields id, title and added, so you can print directly book.id:
{% for book in records.items %}
<tr><td>
{{ book.title }} {{ book.added }}
</td></tr>
{% endfor %}
Good day,
I'm asking myself, if it's possible to transfer multiple informations as primary-keys inside my template!?
For example, when clicking on a link inside my table...
In this case im transfering the item-id:
<tbody>
{% for item in dataset %}
<tr>
<td>
Item-Name
</td>
</tr>
{% endfor %}
</tobdy>
Now I want to transfer the id and - let's say - the name! Is something like this even possible?
<tbody>
{% for item in dataset %}
<tr>
<td>
Item-Name
</td>
</tr>
{% endfor %}
</tobdy>
And if it's possible, do I have to chage something inside my urls.py? Right now it's looking like this:
path('index/<str:pk>', views.example, name="Example"),
Thanks for all your help and a great day!
Your url should be
{% url 'Examplepage' id=item.id name=item.name %}"
And your path should be
path('index/<str:id>/<str:name>/', views.example, name="Example"),
I have followed the code here https://learn.microsoft.com/en-us/outlook/rest/python-tutorialnd and it works however I need to access the calender events for my own purpose.
context = { 'events': events['value'] }
return render(request, 'tutorial/events.html', context)
The HTML is
<table class="table">
<tr>
<th>Subject</th>
<th>Start</th>
<th>End</th>
</tr>
{% for event in events %}
<tr>
<td>{{ event.subject }}</td>
<td>{{ event.start.dateTime }} ({{ event.start.timeZone }})</td>
<td>{{ event.end.dateTime }} ({{ event.end.timeZone }})</td>
</tr>
{% endfor %}
</table>
My question is how can I interrogate context to obtain the data in the format shown above? Ie subject start date time and end date time.
I'm very new to Python.
I've seen how the data is held using debug statements.
See above
I need interrogate context to obtain the data in the format shown above? Ie subject start date time and end date time.
The data in Context looks like this
context data
How does the data get interpreted by the HTML?
From understanding the code above, events['value'] seems like a list of dictionaries. In the python code, you should be able to access it using
for inner_dict in events['value']:
print(inner_dict["subject"])
print(inner_dict["start"]["dateTime"])
print("*****")
The HTML code perhaps interprets it using Template Engine what does {% %} mean in html
I learned the pagination basics for Django from this link:
https://simpleisbetterthancomplex.com/tutorial/2016/08/03/how-to-paginate-with-django.html
However! the only problem I have is that I want to paginate without changing url.
By that, I mean I need to paginate a table while there are multiple tables in a html page.
How do i paginate only one table???
My code:
This is the basic structure of the html template:
...
<table class="uk-table uk-table-striped">
<tbody>
{% for post_status in post.statusPage %}
<tr>
<td>{{ post_status.status_time }}</td>
<td>{{ post_status.repost_count }}</td>
<td>{{ post_status.comment_count }}</td>
<td>{{ post_status.like_count }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% if post.statusPage.has_other_pages %}
<ul class="uk-pagination uk-flex-center" uk-margin>
{% if post.statusPage.has_previous %}
<li><span uk-pagination-previous></span></li>
{% else %}
<li><a><span uk-pagination-previous></span></a></li>
{% endif %}
{% for i in post.statusPage.paginator.page_range %}
{% if post.statusPage.number == i %}
<li class="uk-active"><span>{{ i }}</span></li>
{% else %}
<li>{{ i }}</li>
{% endif %}
{% endfor %}
{% if post.statusPage.has_next %}
<li><span uk-pagination-next></span></li>
{% else %}
<li><a><span uk-pagination-next></span></a></li>
{% endif %}
</ul>
{% endif %}
In side the template, there are multiple post objects
post
Each post has its own table and paginator:
post.statusPage
is the page object of the post.
Rather than building the pagination yourself and dealing with the complexity you're running into, consider using DataTables.
You can place multiple tables on a single view, and the pagination for each table is handled via javascript with no actual change in the URL. You can either insert the values into the table using standard django template tags, or you can build a simple API (using DRF or django's JSON libraries) to feed the tables via Ajax. This is a bit more advanced, but when you have a lot of data, it ensures you aren't sending it all to the user at once and hogging system memory.
I am not sure I know what you're trying to do, but it seems like your view returns a full set of tables, and you'd like the user to be able to view them one at a time, with a click in between, instead of scrolling down forever. You don't want to hit a different URL, so this needs to be handled in the client browser, and that means this is not a Django problem and hence not a Django solution. (Calling it pagination but also wanting it all to appear at the same URL and hence be the same web page is slightly confusing.)
The simplest way from where you are now might be toggling 'show-hide' html divs, that with a button created for each page. So each page is rendered but selectively presented. You'd have to modify the little script there to set all other pages to hidden.
I'm sorry I haven't got a better example for your particular situation. There are probably a bunch of more elegant javascript-heavy solutions out there, but I can't advise you on those.
If you are willing to send querystrings with a Get request for the next page, you could solve this entirely with Django, by creating links that include '?param=' type page numbers. The parameters can then be obtained from 'request.GET.getlist('param')' to return the right page. But if your view returns everything now, you might not want to get into generating and handling querystrings.
Is it possible to switch off Description column in Django Rest Framework Documentation? As you can see on the screenshot below there is a column Description. It is obvious what username and password mean, so I don't need to add more information, however empty cells don't look well. I would like to switch off it only for this method, because for instance in others I would like to have descriptions. Any ideas how can I do this?
There is no easy way to do this at the moment, since that 'Description' column is set at template level. See this template.
To be able to do this in a nicer way you need to customize rest_framework/docs/link.html, maybe have a template tag to check for a custom flag in here:
{% elif link.fields|with_location:'form' %}
<h4>Request Body</h4>
<p>The request body should be a <code>"{{ link.encoding }}"</code> encoded object, containing the following items.</p>
<table class="parameters table table-bordered table-striped">
<thead>
<tr><th>Parameter</th><th>Description</th></tr>
</thead>
<tbody>
{% for field in link.fields|with_location:'form' %}
<tr><td class="parameter-name"><code>{{ field.name }}</code>{% if field.required %} <span class="label label-warning">required</span>{% endif %}</td><td>{% if field.schema.description %}{{ field.schema.description }}{% endif %}</td></tr>
{% endfor %}
</tbody>
</table>
{% endif %}
But I think this is too much to consider just to have that column removed.