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