How to display django model column values horizontally on django template - django

my issue is displaying the model data on django template horizontally. I have a model named "Main" with 3 columns. When I display on the template it looks like this-
I want to filter it by category that will look like this-
Main.objects.filter(category='food')
My goal is to show the category name on the template with the price horizontally on the side with plus signs. It should look something like this-
food= 8+10+11
I tried for...in loop both on template and on views.py both failed. Tried something like this- print(f"{i.category}={i.price}+") with for loop. Didn't work.
output+=f'{i.price}+' with a for loop, holding it in a variable and display that variable on template. Different combinations of those, all failed.
Since += is mainly for integers, I tried with i.price without turning it into a string, failed.
Most answers I found here on "displaying model data horizontally on Django template" are about using css to display form elements side by side,which I know how to do and not exactly my problem.
Can anyone point me to the right direction?
Here is my models.py
class Main(models.Model):
name = models.CharField(max_length = 60, blank = True)
category = models.CharField(max_length = 60, blank = True)
price = models.CharField(max_length = 60, blank = True)
def __str__(self):
return self.name
views.py -
def products(request):
products = Main.objects.all()
context = {'products':products}
return render(request, 'myapp/index.html', context)
and the HTML template -
<div class="card card-body">
<table class="table">
<tr>
<th>Product</th>
<th>Category</th>
<th>Price</th>
</tr>
{% for i in products %}
<tr>
<td>{{i.name}}</td>
<td>{{i.category}}</td>
<td>{{i.price}}</td>
</tr>
{% endfor %}
</table>
</div>
Not the entire template but you get the idea. Very basic.

You can do it like this:
views.py:
def products(request):
foods = Main.objects.filter(category='food').values_lis('category', flat=True)
return render(request, 'myapp/index.html', {'foods': foods})
index.html:
<div class="card card-body">
<p> food:
<span>
{% for food in foods %}
{{ food }} {% if not forloop.last %}+{% endif %}
{% endfor %}
</span>
</p>
</div>

Related

I need help creating a custom counter for items in my SQLite database

I am new to Python and Django and I am trying to count the number items(documents) in my SQLite database base on the status of the document, (canceled or not canceled). I have tried multiple ways to do this but, I cannot find one that works correctly for me. I have tried forloop.counter, .count(), and a few other ways that i found online. All I want to do is go through the database and have it tell me how many canceled procedures I have in the database. I am trying to display the results on a html page. Thanks.
models.py
class posts(models.Model):
OPMnumber = models.CharField(max_length = 30)
title = models.TextField()
contacts = models.CharField(max_length = 50)
dateLastReviewed = models.DateTimeField()
reviewDue = models.DateTimeField()
status = models.CharField(max_length = 20)
assignedTo = models.CharField(max_length = 30)
comments = models.TextField()
views.py
def opmStatistics(request):
"""
Return opmStatus page
"""
entries = posts.objects.all()#[:10] limits the number of entries
displayed
#opm_count = posts.objects.filter(posts.status=='Canceled').count()
#return render_to_response('opmStatistics.html', {'posts' :
opm_count})
return render_to_response('opmStatistics.html', {'posts' : entries})
My html code:
<tr><td>Current Number of Active Accelerator Operations OPMs: </td>
<td>
{% for post in posts %}
{% if post.status != "Canceled" %}
{% with OPM_count=forloop.counter %} <!-- how to save final number
as variable. -->
{{OPM_count}}
{% endwith %}
{% endif %}
{% endfor %}
</td>
</tr>
<br><br>
<tr><td>Current Number of Canceled Accelerator Operations OPMs: </td>
<td>
{% for post in posts %}
{% if post.status == "Canceled" %}
{% with OPM_count=forloop.counter %} <!-- how to save final
number as variable. this one does not reset to 1, starts where
it left off. -->
{{OPM_count}}
{% endwith %}
{% endif %}
{% endfor %}
</td>
</tr>
</table>
If you want to count a single value, then you should do that in the view. This is not at all something you should be attempting to do in the template.
You were almost there with your original attempt. It should be:
def opmStatistics(request):
"""
Return opmStatus page
"""
opm_count = posts.objects.filter(status='Canceled').count()
return render(request, 'opmStatistics.html', {'count': opm_count})
and then the template is just:
<tr>
<td>Current Number of Active Accelerator Operations OPMs: </td>
<td>{{ count }}</td>
</tr>

Django ,How to show image on the board in templates?

I want to use like this
I'm making a bulltein board like the image.
I can show image in detail page. But i can't show image bulletin board list(index page).
How do I add images to the bulletin board list?
toy/models.py
class NewBornProduct(models.Model):
type = models.ForeignKey(Type,on_delete=models.PROTECT)
name = models.CharField(,max_length=30)
content = models.TextField()
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
price = models.IntegerField(null=False)
class NewBornProductImage(models.Model):
product = models.ForeignKey(NewBornProduct,on_delete=models.CASCADE)
image = models.ImageField(upload_to="newborn/%Y/%m/%d")
def delete(self, using=None, keep_parents=False):
self.image.delete()
return models.Model.delete(self, using=using, keep_parents=keep_parents)
toy/views.py
def newborn(request):
obj = NewBornProduct.objects.all()
return render(request,'toy/newborn.html',{'obj':obj})
toy/newborn.html
{% for post in obj %}
<tr>
<th>{{post.id}}</th>
<th> i want to show image here!</th> <-------- Here!
<th>
{{post.name}}
</th>
<th>{{post.price}}</th>
<th>{{post.amount}}</th>
<th>{{post.pub_date}}</th>
</tr>
{% endfor %}
I do not know how to call the image because the other is fine
Do you have any ideas?
If what yoy want is "the first image if there's one":
{% for post in obj %}
<tr>
<th>{{post.id}}</th>
<th>
{% with post.newbornproductimage_set.first as img %}
{% if img %}<img src="{{ img.image.url }}" />{% endif %}
{% endwith %}
</th>
<th>
{{post.name}}
</th>
<th>{{post.price}}</th>
<th>{{post.amount}}</th>
<th>{{post.pub_date}}</th>
</tr>
{% endfor %}
Also note that:
1/ your markup is wrong, you should be using td, not th (th is a table header)
2/ naming your products queryset obj and products instances post is not going to help wrt/ readabilty/maintainability. You should rename obj to products (plural, denotes a collection) and post to product.

Call Django function with argument in html

I am pretty new to django and try to call a django function in html to display how many objects of 'Akte' is in the respective 'Charge' object, but somehow I am missing the right way to do it.
models.py:
class Charge(models.Model):
STATI = (
('O','Offen'),
('G','Geschlossen'),
)
"Projektnr = models.CharField(max_length=30)"
Containernr = models.CharField(max_length=30)
Plombennr = models.CharField(max_length=30)
status = models.CharField(max_length=1, choices=STATI)
def __str__(self):
return self.Containernr
class Akte(models.Model):
Aktenbarcode = models.CharField(max_length=30)
"Eincheckdatum = models.datetime()"
user = models.CharField(max_length=30)
containerId = models.ForeignKey(Charge,on_delete=models.CASCADE)
kundennr = models.CharField(max_length=30)
Startdatum = models.DateField(auto_now_add=True)
def __str__(self):
return self.Aktenbarcode
and this is my views.py:
def tabelle(request):
assert isinstance(request, HttpRequest)
charge_list = Charge.objects.all()
return render(
request,
'app/tabelle.html',
{
'charge_list':charge_list,
}
)
def anzahl(containernr):
return {'anzahl': Akte.objects.filter(containerId__Containernr==containernr).count }
and here is the html code:
{% extends "app/ats.html" %}
{% block content %}
{% if not user.is_anonymous %}
<div style="margin-left:10%;color:white;"><a style="color:white"href="{% url 'home'%}">Home</a> ><a style="color:white"> Tabellenübersicht</a></div>
<div>
<table>
<tr>
<th>Containernummer</th>
<th>Status</th>
<th>Anzahl Akten</th>
<th>Plombennummer</th>
<th></th>
</tr>
{%for Charge in charge_list%}
<tr>
<td>{{Charge.Containernr}}</td>
<td>{{Charge.status}}</td>
<td>{% anzahl Charge.Containernr %}</td>
<td>{{Charge.Plombennr}}</td>
</tr>
{% endfor %}
</table>
</div>
{% endif %}
{% endblock %}
when I try it, I always get this error:
TemplateSyntaxError at /tabelle
Invalid block tag on line 19: 'anzahl(Charge.Containernr)', expected 'empty' or 'endfor'. Did you forget to register or load this tag?
what is the right way to solve this problem?
You can't call methods with arguments in the template. But you don't need to here; to get the count of Akte for that Charge you can do:
{{ Charge.akte_set.count }}
An even better - and much more efficient - approach is to get this data in the original query in your view, via annotation:
from django.db.models import Count
def tabelle(request):
charge_list = Charge.objects.all().annotate(akte_count=Count('akte'))
and now in your template you can do:
{{ Charge.akte_count }}

django filter a regroup within a forloop

I have a model called Subtopic. One of my templates runs a forloop on an object, returning a different field for each cell of a table row.
Two of the table cells look up a field which is a ManytoMany foreign key, both to the same foreign model, Resource. I want each to display different results, based on the value of a boolean field within the Resource model.
What you see below is currently working fine, but doesn't attempt to filter by the boolean field.
models.py:
class ICTResourceManager(models.Manager):
def get_query_set(self):
return super(ICTResourceManager, self).get_query_set().filter('is_ict': True)
class NonICTResourceManager(models.Manager):
def get_query_set(self):
return super(NonICTResourceManager, self).get_query_set().filter('is_ict': False)
class Resource(models.Model):
subtopics = models.ManyToManyField(Subtopic)
external_site = models.ForeignKey(ExternalSite)
link_address = models.URLField(max_length=200, unique=True, verify_exists=False)
requires_login = models.BooleanField()
is_ict = models.BooleanField()
flags = models.ManyToManyField(Flag, blank=True)
comment = models.TextField()
def __unicode__(self):
return u'%s %s' % (self.external_site, self.link_address)
objects = models.Manager()
ict_objects = ICTResourceManager()
nonict_objects = NonICTResourceManager()
class Meta:
ordering = ['external_site', 'link_address']
views.py:
def view_ks5topic(request, modulecode, topicshortname):
listofsubtopics = Subtopic.objects.filter(topic__module__code__iexact = modulecode, topic__shortname__iexact = topicshortname)
themodule = Module.objects.get(code__iexact = modulecode)
thetopic = Topic.objects.get(module__code__iexact = modulecode, shortname__iexact = topicshortname)
return render_to_response('topic_page.html', locals())
My template:
{% for whatever in listofsubtopics %}
<tr>
<td>
{{ whatever.objective_html|safe }}
<p>
{% if request.user.is_authenticated %}
{% with 'objective' as column %}
{% include "edit_text.html" %}
{% endwith %}
{% else %}
{% endif %}
</td>
<td>
{% regroup whatever.resource_set.all by external_site.name as resource_list %}
{% for external_site in resource_list %}
<h4>{{ external_site.grouper }}</h4>
<ul>
{% for item in external_site.list %}
<li>{{ item.comment }}</li>
{% endfor %}
</ul>
{% endfor %}
</td>
</tr>
{% endfor %}
As you can see, I've added extra managers to the model to do the filtering for me, but when I replace the appropriate lines in the template, I just get blanks. I have tried: for external_site.ict_objects in resource_list and for item.ict_objects in resource_list and <a href="{{ item.ict_objects.link_address }}">. If this were in the view I could probably do the filter just by .filter('is_ict': True), but with this being inside a forloop I don't know where to do the filtering.
I also tried writing regroup whatever.resource_set.filter('is_ict': True) in the template, but the syntax for regrouping seems to use resource_set.all rather than resource_set.all() (and I don't know why) so the filter text doesn't work here.
Turns out it was possible to do it using a custom template filter. The original efforts to filter within the template weren't working, given that as is well documented the template language is not a fully-fledged python environment. My original question remains open for anyone who knows an alternative method that more directly addresses the question I was originally asking, but here's how I did it:
myapp_extras.py:
from django import template
register = template.Library()
def ict(value, arg):
"filters on whether the is_ict Boolean is true"
return value.filter(is_ict=arg)
register.filter('ict', ict)
My template, note the use of the custom filter in line 2:
<td>
{% regroup whatever.resource_set.all|ict:1 by external_site.name as resource_list %}
{% for external_site in resource_list %}
<h4>{{ external_site.grouper }}</h4>
<ul>
{% for item in external_site.list %}
<li>{{ item.comment }}</li>
{% endfor %}
</ul>
{% endfor %}
</td>
After this I was able to remove the additional custom managers from the model.
One further question, when filtering for the boolean is_ict field, I found that I had to use filter(is_ict=1) and filter(is_ict=0). Is that the only way to refer to a True or False value?

How can insert Hyperlinks for image fields in Django template

I am displaying the database field names and values in html table in django templae with this code
<table id="listTable" >
<tr>
{% for fieldname in object_fields %}<th>{{ fieldname }}</th>{% endfor %}
</tr>
{% for object in object_list %}
<tr class="{% cycle 'row1' 'row2' as rowcolors %}">
{% for fieldvalue in object %}<td>{{ fieldvalue }}</td>{% endfor %}
</tr>
{% endfor %}
</table>
Now the problem i have one field called image_name and i want that for that there should be hyperlink inserted with the text but how can do that so that other columns don't get affected.
I use this code for all the tables
What I would do in this case is add a property to the class that wraps the value of the field in an anchor tag and add that property to your object_list instead of the default value of the field. Here's a quick and dirty example to get you going.
#models.py
class MyClass(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField()
#property
def email_link(self):
return u'%(email)s' % {'email' : self.email}