Get data from the database into the main django admin page - django

i want to put some data from the database into the admin index page, so i am trying to add some code to the index.html, but the commands such as Model_name.object.get() don't seem to work there
<ul>{% trans 'Last Update at ' %}
{% for entryupdate in Updatetime.objects.all %}
{{ entryupdate.updatetime }}
{% endfor %}
</ul>
so what shall i use instead? The problem is that there is no variable associated with the object i need. If that would have been any other page i could have added the variable in the views.py, but that's not the case. Thank you!

Those sorts of functions don't work in any template.
You should use a custom template tag to query the data and return it.

Thank to the tip of Daniel i created that tag:
import datetime
from django import template
from Myapp.models import Updatetime
register = template.Library()
def update_time():
ss = Updatetime.objects.get(pk=1)
str11 = ss.updatetime.strftime("%d-%m-%Y %H:%M:%S")
return str11
register.simple_tag(update_time)

Related

Django - add link with custom admin page href

In my Django project, I have created a custom admin page for an app via the get_urls() method. I'd like to add a link to the app's main model index view that will take users to this custom page - however, I'm having some trouble creating this link element correctly and I don't seem to be able to piece together the right way to do it - I'm just left with a Reverse for 'export' not found. 'export' is not a valid view function or pattern name. error.
I've set up the admin for the app like so:
# my_project/observations/admin.py
from django.template.response import TemplateResponse
from django.urls import path
class ObservationAdmin(SimpleHistoryAdmin, SoftDeletionModelAdmin):
change_list_template = 'export_link.html'
def get_urls(self):
urls = super().get_urls()
custom_urls = [
path('export/', self.admin_site.admin_view(self.export_view), name='export')
]
return custom_urls + urls
def export_view(self, request):
context = dict(
self.admin_site.each_context(request),
)
return TemplateResponse(request, 'export.html', context)
and the two templates that are referenced:
# my_project/observations/templates/export.html
{% extends "admin/base_site.html" %}
{% block content %}
<div>
Some custom content
</div>
{% endblock %}
# my_project/observations/templates/export_link.html
{% extends 'admin/change_list.html' %}
{% block object-tools-items %}
<li>
Export
</li>
{{ block.super }}
{% endblock %}
Navigating directly to http://localhost:8000/admin/observations/observation/export/ works perfectly, I see the custom content page exactly as I want it... so the issue I'm striking is with the link template - I get the Reverse... error when I navigate to the model index page.
Perhaps the argument I'm passing to url is incorrect, or I need to register that URL elsewhere - but I don't quite know. The other examples of link elements like this that I've been able to find don't reference URLs created via the admin class' get_urls() method - so any guidance on this would be greatly appreciated.
Thanks very much, let me know if there's any other info that I can provide to help sort this out.
I think the problems is in missing namespace in your export_link.html template. Instead of:
Export
try:
Export

django - Count objects and sum values in a field

I want to include some basic statistics about a model in a stats.html file. The variables don't show in the html. What am I doing wrong?
from django.shortcuts import render, get_object_or_404, redirect
from django.db.models import Avg, Sum, Count
from .models import Production
def statistics(request):
nr_of_plays = Production.objects.count()
nr_of_actors = Production.objects.aggregate(num_actors=Sum('nr_actors'))
nr_of_audience = Production.objects.aggregate(num_audience=Sum('est_audience'))
context = {
'nr_of_plays': nr_of_plays,
'nr_of_actors': nr_of_actors['num_actors'],
'nr_of_audience': nr_of_audience['num_audience'],
'test':'abc'
}
return render(request, 'stats.html', context)
The model:
class Production(models.Model):
title = models.CharField(max_length=200)
nr_actors = models.IntegerField(default=0)
est_audience = models.IntegerField(default=0)
...
urls.py:
path('stats/', views.statistics, name='stats'),
the relevant section of base.html:
<copyright class="text-muted">
<div class="container text-center">
<p>© One World Theatre - {% now "Y" %} {% include 'stats.html' with test=test %} </p>
</div>
</copyright>
And the stats.html template:
{% load static %}
{{ test }} - Stats: {{ nr_of_plays }} plays produced, involving {{ nr_of_actors }} actors, seen by {{ nr_of_audience }} people.
the output:
© One World Theatre - 2020 - Stats: plays produced, involving actors, seen by people.
EDIT:
I didn't mention that I'm using my template stats.html in my base.html template like this {% include 'stats.html' %}. When I add with test=test to the include tag, the test text shows. But when adding with nr_of_plays=nr_of_plays nothing happens :-/.
I ended up forgetting about trying to {% include 'stats.html' %} in my base template and just added those variables where I need them, works great. Not DRY, but what to do... .
EDIT 2:
I was too quick to cry victory. Edited the question with the latest code. Passing the variables in the view that handles the main content block works, but that means I would have to add them in every single view (not DRY). Still not getting what doesn't work with my setup. example.com/stats.html renders exactly what I want, but doesn't show the variables when I include it in my base.html. with test=test doesn't do anything. Clueless (and thankful for the help sofar).
Aggregate returns a dictionary.
You need to access its value via the key
context = {
'nr_of_plays': nr_of_plays,
'nr_of_actors': nr_of_actors['nr_actors_sum'],
'nr_of_audience': nr_of_audience['est_audience_sum']
}
Alternatively you can specify a custom key name instead of the default composite one:
nr_of_actors = Production.objects.aggregate(num_actors=Sum('nr_actors'))
nr_of_audience = Production.objects.aggregate(num_audience=Sum('est_audience'))
Note: .all() is redundant and can be removed
Base on your latest confession and symptoms, you don't seem to be going to your statistics view.
Looks like the url is rendering another view, which also extends base.html confuses you that you are in the right view.
One way to test it is to put a print statement in your statistics view and see if it prints anything in the console:
def statistics(request):
print(111111111111111111111111111111)
...
return render(request, 'stats.html', context)
Second thing is, if your base.html includes stats.html, you shouldn't be rendering the stats.html directly, you should pass the context to a template that extends base.html.
Third thing is, refer to Pynchia's answer to properly get the count of aggregated queryset.

Make a change to a string in django template?

I have a queryset in Django that contains a string field. This is a filename, something like images/photo.jpg or images/photo.20.19.22.jpg. I need to rewrite them in one particular view so that ".thumbnail" is inserted before the extension. The previous names should become images/photo.thumbnail.jpg and images/photo.20.19.22.thumbnail.jpg.
What is the best way to do this? This is part of a queryset so it will look like:
{% for record in list %}
{{ record.image }}
{% endfor %}
Now of course I would love to do this outside of my template. However, I don't see a way in which I can do that. After all, this needs to be done for every record inside my queryset. To complicate things, this record does not come directly from a modal. This record is coming from a subquery, so I don't see a way for me to change the modal itself. Should I use templatetags for this? Any other recommendations?
FYI the subquery is something like this:
>>> from django.db.models import OuterRef, Subquery
>>> newest = Comment.objects.filter(post=OuterRef('pk')).order_by('-created_at')
>>> Post.objects.annotate(image=Subquery(newest.values('image')[:1]))
A simple custom template filter could do this.
#register.filter
def add_thumbnail(image):
return image.replace('.jpg', 'thumbnail.jpg')
And in the template:
{% for record in list %}
{{ record.image|add_thumbnail }}
{% endfor %}

'My_Model' object is not iterable using customtag in django

I am new to Django and I am trying to make my data accessible to templates in different apps by creating custom tags in Django.
my model.py
from django.db import models
class my_Model(models.Model):
name = models.CharField(max_length=20)
age = models.CharField(max_length=20)
my custom tag file templatetag/custom_tag.py(why I did this is to make my data accessible to templates in different apps)
from django import template
from model_file.models import my_Model
register = template.Library()
#register.simple_tag
def get_custom_tag_fn():
return my_Model.objects.order_by('-pk')[0]
my html file
{% load custom_tag %}
{% get_custom_tag_fn as ct %}
{% for item in ct %}
<p> {{ item }} </p>
{% endfor %}
I am getting the error 'My_Model' object is not iterable. Any thought about how to solve this.
The problem is here:
return my_Model.objects.order_by('-pk')[0]
Model objects.order_by(...) returns queryset, alike to the list it`s a collection, so with [0] index you take the first object of that collection which of course is not iterable (it's just a single object). So, after that, when you trying to iterate:
{% for item in ct %}
...
you`re catching this error.

formatting table cell content in django-tables2

Love django-tables... but something that I'm sure is trivial to solve is giving me fits. When the value I pass for a given row/column is like:
some<br/>random<br/>words<br/>returned
I want the browser to parse and render the content in that cell... to look like this:
somerandomwordsreturned
not escape the content I'm passing and display it like this:
some<br/>random<br/>words<br/>returned
Surely there's some flag or option that I've missed?
Use mark_safe as follows:
import django_tables2 as tables
from django.utils.safestring import mark_safe
class testTable(tables.Tables):
id = tables.Column()
html = tables.Column()
def render_html(self):
return mark_safe('some<br/>random<br/>words<br/>returned')
Same question was asked in this thread
If some of your data already contains HTML, the simplest solution is to use a TemplateColumn rather than a normal column and mark the value as safe:
class Table(tables.Table):
html_data = tables.TemplateColumn("{{ value|safe }}")
# ...
HA. Found it. It wasn't django-tables2 that was auto-escaping my content, it was the django templating system itself: https://code.djangoproject.com/wiki/AutoEscaping.
I had to change my template code to render the django-table2 like this:
{% autoescape off %}
{% load render_table from django_tables2 %}
{% render_table route_table %}
{% endautoescape %}
If you want to render as html your column value
import django_tables2 as tables
from django.utils.safestring import mark_safe
class testTable(tables.Tables):
# column 1
html = tables.Column()
# ....
def render_html(self, value):
return mark_safe(value)