How to switch off Description column in Django Rest Framework Documentation? - python

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.

Related

Publish JSON data into a date based table using Flask Jinja2 template

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.

Django: Transfer multiple data into next template

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"),

Django: Pagination without changing url?

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.

How do I get the latest post in a topic?

In the table, I want to show the latest post from that topic. My post model is called post. I have listed my code below.
forum.html:
{% for category in categories %}
<h5 class="blue-text">{{ category.title }}</h5>
<table>
<thead>
<tr>
<th>Icon</th>
<th>Name</th>
<th>Latest Post</th>
</tr>
</thead>
{% for topic in category.topic_set.all %}
<tbody>
<tr>
<td><i class="material-icons black-text">{{ topic.icon }}</i></td>
<td>{{ topic.title }} <br> <span class="grey-text">{{ topic.description }}</span></td>
<td>post_title <br> <span class="grey-text">post_author</span> <br> <span class="grey-text">post_created_at_timesince</span></td>
</tr>
{% empty %}
<p>No topics in {{ category.title }}</p>
{% endfor %}
</tbody>
</table>
{% empty %}
<p>No categories.</p>
{% endfor %}
views.py:
def forums(request):
categories = Category.objects.all()
topics = Topic.objects.all()
return render(request, 'forum.html', {'categories': categories, 'topics': topics})
If you need anymore details let me know.
Thanks,
Cameron.
use Topic.objects.order_by('-createtime') to order them by createtime. If you don't have createtime in your field, you can use -id instead since the lastest topic has the largest id.
To get the latest topic, you would do something like,
latest_topic = Topic.objects.order_by('-createtime')[-1]
or
latest_topic = Topic.objects.order_by('-id')[-1]
This can be done in following way. You can change your view like this
from django.db.models import Prefetch
def forums(request):
topics = Topic.objects.all().order_by('-created_time')
categories = Category.objects.all().prefetch_related(Prefetch('topic_set', queryset=topics)
return render(request, 'forum.html', {'categories': categories})
Above code snippet has two advantages:
You will get latest post when you do {% for topic in category.topic_set.all %}.
No extra query will execute for the above statement in the template.
You can add topics in the context if you are using at some other place also. For the given case, you do not need to send it in the context since you are getting the data from the category object.
If you require that you need to get latest post of category at multiple places, then you can also use ordering attribute in the meta class of the topics model.
You can find more details here https://docs.djangoproject.com/en/2.0/ref/models/options/#ordering.

Pandas Dataframe display on a webpage

I am using Flask but this probably applies to a lot of similar frameworks.
I construct a pandas Dataframe, e.g.
#app.route('/analysis/<filename>')
def analysis(filename):
x = pd.DataFrame(np.random.randn(20, 5))
return render_template("analysis.html", name=filename, data=x)
The template analysis.html looks like
{% extends "base.html" %}
{% block content %}
<h1>{{name}}</h1>
{{data}}
{% endblock %}
This works but the output looks horrible. It doesn't use linebreaks etc.
I have played with data.to_html() and data.to_string()
What's the easiest way to display a frame?
The following should work:
#app.route('/analysis/<filename>')
def analysis(filename):
x = pd.DataFrame(np.random.randn(20, 5))
return render_template("analysis.html", name=filename, data=x.to_html())
# ^^^^^^^^^
Check the documentation for additional options like CSS styling.
Additionally, you need to adjust your template like so:
{% extends "base.html" %}
{% block content %}
<h1>{{name}}</h1>
{{data | safe}}
{% endblock %}
in order to tell Jinja you're passing in markup. Thanks to #SeanVieira for the tip.
Ok, I have managed to get some very nice results by now combining the hints I got here. In the actual Python viewer I use
#app.route('/analysis/<filename>')
def analysis(filename):
x = pd.DataFrame(np.random.randn(20, 5))
return render_template("analysis.html", name=filename, data=x)
e.g. I send the complete dataframe to the html template. My html template is based on bootstrap. Hence I can simply write
{% extends "base.html" %}
{% block content %}
<h1>{{name}}</h1>
{{ data.to_html(classes="table table-striped") | safe}}
{% endblock %}
There are numerous other options with bootstrap, check out here:
http://getbootstrap.com/css/#tables
Base.html is essentially copied from here
http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-xii-facelift
The next question is obviously how to plot such a frame. Anyone any experience with Bokeh?
Thank you both to Matt and Sean.
thomas
Iterating over the rows of a df
If you need to have the df in a format that can iterate over the rows in your html, then use to_dict(orient='records'), which produces a dict in a format:
‘records’ : list like [{column -> value}, … , {column -> value}]
That way you can use your own way of displaying the data in your html.
The sample code would now look like this:
Python code using flask
#app.route('/analysis/<filename>')
def analysis(filename):
x = pd.DataFrame(np.random.randn(20, 5))
return render_template("analysis.html", name=filename, data=x.to_dict(orient='records'))
HTML code with jinja
{% extends "base.html" %}
{% block content %}
<table class="table">
<thead>
<tr>
<th scope="col">Column name 1</th>
<th scope="col">Column name 2</th>
<th scope="col">Column name 3</th>
</tr>
</thead>
<tbody>
{% for row in data %}
<tr>
<td>{{row['Column name 1']}}</td>
<td>{{row['Column name 2']}}</td>
<td>{{row['Column name 2']}}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
You can use enaml-web to display and interact with pandas dataframes.
A few examples:
With filtering - https://github.com/frmdstryr/smd-search
Simple viewer - https://github.com/codelv/enaml-web/tree/master/examples/dataframe_viewer
Note: Interaction (sorting, filtering, etc...) requires a server with websocket support.

Categories