Django template: How to use values/values_list - django

In template I am trying to do something like this:
{{ request.user.profile.following.all.values_list }}
and I get
<QuerySet [(7, 2, 1)]>
, but I want to get
<QuerySet [2]>
like in Django values_list.
For example: Follow.objects.filter(follow_by=self.request.user.profile).values_list('follow_to', flat=True)
Can I pass argument like this in template?

Can I pass argument like this in template?
No. The Django template engine deliberately restricts this, since this is logic that belongs in the view. For example:
from django.contrib.auth.decorators import login_required
#login_required
def my_view(request):
following = request.user.profile.following.values_list('follow_to', flat=True)
return render(
request,
'some_template.html',
{'following': following}
)
You can then render this with:
{{ following }}
That being said, using .values_list(…) [Django-doc] is often an anti-pattern, since it erodes the model layer. It is thus something related to the primitive obsession antipattern [refactoring.guru].

Related

How do I get the url for a model?

Given the following situation:
# models.py
class Book(Model):
pass
# views.py
class BookDetail(DetailView):
model = Book
# books/urls.py
urlpatterns += [path('detail/<int:pk>', BookDetail.as_view(), 'book_detail')]
# page/urls.py
urlpatterns += [path('books/', include('books.urls'))]
I can load the detail view for the object with the private key id 42 at /books/detail/42/. If I am in another request with a completely different path and hold a reference to the object with the private key id 42, is there an "official" or builtin way to generate the url /books/detail/42/? Preferably outside of templating, so I can respond with a JSON.
Or is the idiomatic way to parametrize the path elements (books and detail) and just rebuild it myself?
Yes, you can make use of get_absolute_url for model-specific views and the {% url ... %} template tag to calculate the name of a view.
Model-specific views
If a Model has a specific view to show details, you can implement a get_absolute_url [Django-doc] on your model, like:
from django.urls import reverse
class Book(Model):
def get_absolute_url(self):
return reverse('book_detail', kwargs={'pk': self.pk})
Here we use reverse [Django-doc] to "calculate" the URL for the given name of the view (specified in your path(..., name='book_detail')) with as pk parameter, the pk of self.
In your template you can then write:
{{ my_object }}
with my_object the name of the variable in your template.
It is note that the redirect [Django-doc] function understands the get_absolute_url, and thus you can write return redirect(my_object) in a view, and it will automatically call get_absolute_url to redirect to the proper view.
If you serialize a model with the Django REST framework, then you can reuse the get_absolute_url as well, by using a URLField [drf-doc] for example:
from rest_framework.serializers import ModelSerializer, URLField
class BookSerializer(serializers.ModelSerializer):
absolute_url = serializers.URLField(
read_only=True,
source='get_absolute_url'
)
This specific use case is documented in the documentation of the Django REST framework.
Making use of {% url ...%} in the template
You can also calculate the URL of a view, by using the {% url ... %} template tag [Django-doc]. You can for example write:
{{ my_object }}
to calculate the URL, just like we did with the get_absolute_url. It is however useful as well for other, non model-specific views.
You should use Django Rest Framework
All built-in, you just have to set up.

Django 'could not parse remainder' on related model call in template

When I try to call this in my template
{% if member.departments.relationship(department).is_manager is True %}
I get this error
Could not parse the remainder: '(department).is_manager' from 'member.departments.relationship(department).is_manager'
But the same call works when I debug my view
(Pdb) member.departments.relationship(department).is_manager
True
Here is my view
def department_detail(request, uid):
department = Department.nodes.get(uid=uid)
return render(request, 'department/detail.html', {'department': department,})
To solve it, I made use of templatetags. Fun and powerful to learn:
Added /templatetags to same directory as models.py
Added /templatetags/init.py
Added /templatetags/department_extras.py
department_extras.py:
from django import template
from django.utils.safestring import mark_safe
register = template.Library()
#register.filter
def check_is_manager(member, department):
if member.departments.relationship(department).is_manager is True:
html_response = """<i class="fa fa-user-tie" title="Manager"></i>"""
else:
html_response = ""
return mark_safe(html_response)
then in template:
{% load department_extras %}
{{member|check_is_manager:department}}
Disclaimer: If I was using a standard ORM then I would not have this problem, and I am only using it for visual effect, not business logic. If it weren't for the fact that 3 views and other models will need the same functionality, then I would have passed in an additional argument to the template.
I like templatetags because they are almost like sub-views that can act as common denominators across views so that you don't have to keep passing in supplemental data in your arguments of each view.

Django {{ user }} does not return user object in templates without generic views

If some template requests from generic views I can get {{ user }} and it will be an object of authenticated user (e.g. me).
But if I work without generic views, with usual views {{ user }} does not return my object.
Why???
Thanks.
Because you haven't included it in your template render context.
You need to use something like:
def my_view(request, …):
…
return render_to_response("my_template.html", {
…,
"user": request.user,
})
If you're using render_to_response() then you need to add third parameter with RequestContext instance:
return render_to_response('my_template.html',
{'my_data', my_data},
context_instance=RequestContext(request))
More details at https://docs.djangoproject.com/en/dev/topics/http/shortcuts/#django.shortcuts.render_to_response

Sending an object with request

In the below code i am trying to send a object with the request,Is this correct if so how to decode it in template
def index(request):
cat = Category.objects.filter(title="ASD")
dict = {'cat' : cat}
request.update('dict' : dict)
#or
request.dict=dict;
And In the templates can we write the code as
{% for obj in request.dict%}
obj.title
{% endfor %}
EDIT:
If i am calling function like
def post_list(request, page=0, paginate_by=20, **kwargs):
logging.debug("post_list")
page_size = getattr(settings,'BLOG_PAGESIZE', paginate_by)
return list_detail.object_list(
request,
queryset=Post.objects.published(),
paginate_by=page_size,
page=page,
**kwargs
)
You could do this, but why would you want to? Django has a simple, well-defined and well-documented way of passing data into templates - through the context. Why try and find ways to work around that?
Edit after comment No. Again, Django has a perfectly good way of passing extra context into a generic view, via the extra_context parameter which again is well-documented.
You're not showing the actual function you use to render your view (render(), render_to_response(), etc.).
Let's say you are using render_to_response() :
render_to_response(template_name[, dictionary][, context_instance][, mimetype])
Renders a given template with a given
context dictionary and returns an
HttpResponse object with that rendered
text.
So if you pass in {"foo": your_object} as a dictionary you can use {{ foo }} directly in your template.
If you are using the object_list generic view you should use the extra_context:
extra_context: A dictionary of values
to add to the template context. By
default, this is an empty dictionary.
If a value in the dictionary is
callable, the generic view will call
it just before rendering the template.

Possible to send 2 querysets to response?

render_to_response Is it possible to pass more variables than just one? For example in my application I have a members model and then i would like to display the members information and also attendance information. Would I have to supply the arguments as a tuple?
Thanks in Advance,
Dean
Render_to_response accepts a context which is used for rendering. As far as I know there is no limitation on the number of variables you can pass in the context. This includes QuerySets. For example:
def my_view(request, *args, **kwargs):
# ... etc ...
q1 = Model1.objects.filter(**conditions)
q2 = Model2.objects.filter(**conditions)
context = dict(q1 = q1, q2 = q2)
return render_to_response('my_template.html', context_instance = RequestContext(request, context))
My example uses RequestContext but it should be fine without it too.
# Template
{% for foo in q1 %} {{ foo }} {% endfor %}
... stuff ...
{% for bar in q2 %} {{ bar }} {% endfor %}
While Manoj is correct that you can pass variables by constructing your own context instance and passing it as a keyword argument to render_to_response, it's often shorter/simpler to use the second positional argument to render_to_response which accepts a dictionary that gets added to the context behind the scenes.
Take a quick look at the docs for render_to_response. Their example usage looks like this (and allows you to pass anything that can be stored in a dict to the renderer):
from django.shortcuts import render_to_response
def my_view(request):
# View code here...
return render_to_response('myapp/index.html', {"foo": "bar"},
mimetype="application/xhtml+xml")