I am using jinja2 as the templating engine for django app. I wanted to make query in the template. I tried doing this:
{% for f in fs %}
{% Following.objects.filter(follows=f).count() %}
{% endfor %}
I'm passing 'fs' in variables while rendering the templates which a list.
But, its wrong. I can't do the 'query_set' call because of the way my models are defined. Here is a snippet:
class Following(models.Model):
user = models.ForeignKey(User)
follows = models.ForeignKey(F)
class F(models.Model):
name = models.CharField(max_length=50)
So, is there a possible way to do this?
If you are using jinja2 rather than the normal Django template language, what you have should work: you don't say why it doesn't.
But nevertheless, there's no need to define a separate method. You can use the automatic reverse relationship accessor:
{{ f.following_set.count() }}
You can't call methods that take parameter from django template. To overcome this, you can define method in your F model to get the required count.
For example:
class F(models.Model):
name = models.CharField(max_length=50)
def get_follow_count(self):
Following.objects.filter(follows=self).count()
Then in template you can do
{% for f in fs %}
{{ f.get_follow_count }}
{% endfor %}
Related
I am not able to use the Django model object in Django templates. I want to iterate using the model user in the template and then play with the ActivityPeriod(model) of that user. Please check my code for the clarity:
Here is my code:
views.py
from .models import User,ActivityPeriod
def call_response(request):
user = User.objects.all()
return render(request, "Test/list.html", {"users":user ,"activityperiod":ActivityPeriod})
Test/list.html
{% for user in users %}
'real_name': {{ user.real_name}}},
'activity_periods': {% with activity=activityperiod.objects.get(id =user) %}
{{ activity.start_time }}
{% endwith %}
{% endfor %}
But i am getting an error:
Could not parse the remainder: '(id' from 'activityperiod.objects.get(id'
What is the correct way? Can anyone please share it with me.
Django template don't understand the filter action of Model. This part shoud be in view.
activity=activityperiod.objects.get(id =user)
You should prepare your data and manipulate them before sending to template (a dictionary may help you). And remember that result of action "User.objects.all()" is a list.
views.py
def call_response(request):
user = User.objects.filter(user=request.user)
activityperiod = activityperiod.objects.get(user=user)
context={'user':user,'activityperiod':activityperiod}
return render(request, "Test/list.html",context})
Test/list.html
'real_name': {{ user.real_name}}
'activity_periods':{{ activityperiod.start_time }}
Your question suggests that you think you can a function in the templates like a normal function (ie activityperiod.objects.get(...)).
You can't, the templating system is not made like this (for security reasons amongst others).
You should do something like, in your models:
def call_response(request):
# ! first() not "all()" (if > 1 user, you'll have problem)!
user = User.objects.first()
activityperiod = activityperiod.objects.get(user=user)
return render(request, "Test/list.html",
{"users":user ,"activityperiod":activityperiod})
Below is the code for a project I'm working on. As you can see in the view, I'm running a query for objects in the Risk model that are associated with the primary key in the Url.
The problem is that I can't access the attributes of the object being queried.
Model
class Risk(models.Model):
risk_title = models.CharField(max_length=60)
root_causes = models.ManyToManyField('self',
through='Roots',
symmetrical=False,
related_name='root_cause')
class Roots(models.Model):
causal_risk = models.ForeignKey(Risk, related_name='causes', on_delete=models.CASCADE)
effected_risk = models.ForeignKey(Risk, related_name='effected_risk', on_delete=models.CASCADE)
View:
def view_risk(request, id):
try:
risk = Risk.objects.get(pk=id)
except Risk.DoesNotExist:
raise Http404("Risk does not exist")
roots = Roots.objects.filter(effected_risk=id)
args = {
'risk': risk,
'roots': roots,
}
return render(request, 'risks/risk_detail.html', args)
Template:
{% for root in roots %}
{{ root }}
{% endfor %}
Running the above code returns this:
Roots object (2) Roots object (3)
This should be expected, as these are the entries I've made to the model through the admin interface.
However, when I run:
{% for root in roots %}
{{ root.risk_title }}
{% endfor %}
The screen is left blank.
TLDR
Passing the query from the intermediary table to the template works, but the template can't access the object attributes. How can I run the above query and then access the objects in the template?
UPDATEDIncluded the render portion per JoJo's response. This problem has been solved per my other update.
Thank you in advance!
Note that the view function is missing the return statement, so there is actually no html page rendered at all.
Assuming that the template html is named 'my_template.html', the missing return should look something like:
def view_risk(request, id):
# ...
return render(request, 'my_template.html', args)
Further, as #JonHrovat mentioned, the template needs to call
{{ root.causal_risk.risk_title }}
within the for loop.
A note on efficiency:
If you call root.causal_risk.risk_title within the template with your current query for roots this leads to additional queries, one for each iteration. This can be avoided by using the select-related statement when querying for the roots in the view function:
roots = Roots.objects.select_related('causal_risk__risk_title').filter(effected_risk=id)
I forgot to query the direct attributes of the model. I got what I need with this template:
{% for root in roots %}
{{ root.causal_risk.risk_title }}
{% endfor %}
I am having an issue with templating system in Django, I am doing a Movie list app just to learn more about Django and I have already declared my models like following:
class Pelicula (models.Model):
nombre = models.CharField(max_length = 30)
genero = models.CharField(max_length = 20)
año = models.IntegerField()
def __str__(self):
return self.nombre
Then I have declared my view like following
def index(request):
pelicula = Pelicula.objects.all()
return render_to_response("index.html", dict(pelicula = pelicula, usuario = request.user))
So as far as i know, I am not having any trouble here
Then the problem starts on my template
<!DOCTYPE html>
<html>
<head>
<title>Mis peliculas favoritas</title>
</head>
<body>
<h1>Mis peliculas favoritas</h1>
<ol>
{% for pelicula in pelicula.object_list %}
<li>{{ pelicula.nombre }}</li>
{% endfor %}
</ol>
agregar pelicula nueva
</body>
</html>
So as you see, I am using a for loop to get all the objects in my db, I have 3, but when i run the server, the title shows up and the other link bellow named "agregar" shows up except for the movies, I am wondering if the problem is something between the "pelicula" name instead of using Pelicula as i used on declaring my model, anyway I have also changed that to Pelicula.object_list and it didn't worked anyway
I believe I am having a trouble understanding how to use the information i have through Django template tags
Thanks in advance and please forgive my grammar as I am not a native english speaker
In the view code you have pelicula = Pelicula.objects.all() which creates a list of all the abjects from the database. You then send this to the template with the same name, which means all you have to do in the template is iterate over them. Try changing the template to this:
<h1>Mis peliculas favoritas</h1>
{% if pelicula %}
<ol>
{% for item in pelicula %}
<li>{{ item.nombre }}</li>
{% endfor %}
</ol>
{% else %}
didn't find any...
{% endif %}
Part of the confusion seems to come from the fact that the template code and the view code is separate. The template doesn't know anything about the view code. The context dictionary just sets the names that can be used in the template and in the template the only names that you have available to use are the ones that you passed to it via the dictionary. The names in the view and template here are the same in this case because you set them to be the same. They aren't the same variables though, they just have the same name. In the template pelicula is already a list of objects so you don't need to do anything extra to use it in the template loop.
I am developing an application with Django framework and I'm new to it
I need to create a query that simply joins 2 tables( type and subType ) and then later on use the result in the views the models file looks like this:
class Type(models.Model):
name = models.CharField(max_length=60)
description = models.CharField(max_length=200)
class SubType(models.Model):
name = models.CharField(max_length=60)
description = models.CharField(max_length = 200)
Type = models.ForeignKey(Type)
And in home.html file I have : (I dropped out the bootstrap code to make it more readable )
<ul>
<li ><a href="/home" >Home Page</a></li>
{% for type in all_types %}
<li >
{{ type.name }}
<ul >
--The Inner Loop--
</ul>
</li>
{% endfor %}
</ul>
I need to create an list of types and then inside each type I need to create another list which contains the subTypes of each type
I have no idea how do I have to create the query inside the views.py
def index(request):
list_all_types = #Here I have to create a join query via django models
t = loader.get_template('home.html');
c = Context({
'all_types' : list_all_types,
});
return HttpResponse(t.render(c));
So please let me know how do I have to make the query and replace the correct code with the comment part in views.py and what changes do I have to add to make to the home.html to make it enabled show all the subTypes instead of --inner loop in home.html
Thanks in advance
You don't need to do anything in the view other than get the types:
types = Type.objects.all()
In the template, you just iterate over type.subtype_set.all:
<ul>
{% for subtype in type.subtype_set.all %}
<li>{{ subtype.name }}</li>
{% endfor %}
</ul>
Note that this is well covered by the tutorial. (As is the use of the render shortcut rather than loading and rendering the template separately.)
(Actually, what I said at first was not quite true: for the sake of efficiency, you can add prefetch_related() to the Type query.)
I have a variable:
m2m_links = mymodel._meta.many_to_many
This has all of the fields that are m2m in a particular model. I want the template to display the names of the models that are linked. Within my view, I can list the tables like so:
for f in m2m_links:
print f.related.parent_model
But in my template, if I try
{% for table in m2m_links %}
{{ table.related.parent_model }}<br>
{% endfor %}
I get an error: "Caught DoesNotExist while rendering"
How do I get the names of the tables to render in the template? And a further question, how do I get just the name, not something like
<class 'myapp.models.ModelName'>
which is what I have showing in my terminal from the "print" statement.
There's no reason, based on the template code you've provided that you should be getting that error. Most likely, there's something else going on in your template that is causing that.
As for your second question, the way to get a class' name is:
some_class.__name__
However, the Django template engine will not allow you to use underscored properties in the template, so your best bet is to prepare a proper list in your view:
linked_models = [m2m.related.parent_model.__name__ for m2m in mymodel._meta.many_to_many]
Then, just loop through that in your template and the all the work is already done.
UPDATE (based on comment)
You do it mostly the same way, though you have a couple of choices.
You can do a list of tuples and unpack it in the template:
linked_models = [(m2m.related.parent_model.__name__, m2m.related.parent_model._meta.verbose_name) for m2m in mymodel._meta.many_to_many]
Then, in your template:
{% for class_name, verbose_name in linked_models %}
{{ class_name }} {{ verbose_name }}
{% endfor %}
Create a list of dictionaries and reference the keys in the template:
linked_models = [{'class_name': m2m.related.parent_model.__name__, 'verbose_name': m2m.related.parent_model._meta.verbose_name} for m2m in mymodel._meta.many_to_many]
Them, in your template:
{% for model in linked_models %}
{{ model.class_name }} {{ model.verbose_name }}
{% endfor %}