how to use django model object in django templates? - python

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})

Related

Django Check for user in list

I'm creating a django blog app where users can add comments to articles.
I want to remove the post button when the user has already commented.
I have a model named article and another one named comment (with ForeignKey to article)
I tried {% if any request.user in article.comment_set.all} but that doesn't work. I tried to loop over article.comment_set.all but that didn't work either.
Is there a method to do this in the template?
Rather than doing that in template, why don't you do that in view and send it via context. For example:
def view(request):
...
user_exists = article.comment_set.filter(user=request.user).exists()
context = {}
context['user_exists'] = user_exists
return render(request, 'template.html', context)
in template:
{% if user_exists %}
// do something
{% else %}
// do something else
{% endif %}

Django - Show/hide urls in base html dependant on user group?

I want to try and show or hide urls in my navigation page based on user group.
currently i am adding to the top of every view and sending through a value to the template and checking against that, but this doesnt seem too efficient, also if a view does not require auth and that value is not set, will that break the template?
is there a better way to do this?
like a global.py where i could check and set then use it in any template? or something completely different altogether?
view.py
Authorised_user = ''
if request.user.is_authenticated():
Authorised_user = 'IT'
#login_required
def index(request):
return render(request, 'service/index.html', {
'Authorised': Authorised_user,
})
template.html
{% if Authorised == 'IT' or Authorised =='Netwworks' %}
Link
{% endif %}
i do have the user groups in django admin
Based on Get user group in a template
Create user_tags.py / group_tags.py at an appropriate place. e.g. auth_extra/templatetags/user_tags.py
from django import template
register = template.Library()
#register.filter('in_group')
def in_group(user, group_name):
return user.groups.filter(name=group_name).exists()
Then in your template:
{% load user_tags %}
{% if request.user|in_group:"IT"%}
IT only link
{% endif %}
{% if request.user|in_group:"Netwworks"%}
Netwworks only link
{% endif %}
Easiest way around this for me was https://stackoverflow.com/a/17087532/8326187.
Here you don't have to create a custom template tag.
{% if request.user.groups.all.0.name == "groupname" %}
...
{% endif %}
You need to create context_processors.py and create a function say
def foo():
Authorised_user = ''
if request.user.is_authenticated():
Authorised_user = 'IT'
Then in setttings
TEMPLATE_CONTEXT_PROCESSORS = ("path_to_context_processor.foo")
this way you can use foo variable in all the templates without explicitly defining in all the views.
You can also have a look here:https://rubayeet.wordpress.com/2009/10/31/django-how-to-make-a-variable-available-in-all-templates/

Django template: how to randomize order when populating page with objects?

I have a Survey and a Choice model, and each survey has a number of choices associated with it. When I'm rendering the actual HTML survey page with all the choices, I use the following Django templating code:
{% for choice in survey.choice_set.all %}
<li class="ui-state-default" choice_id={{ choice.id }}>{{ choice.choice_text }}</li>
{% endfor %}
However, instead of the choices appearing in the same order every time, I'd like them to populate in a random order to reduce any potential bias effect (e.g. someone may be more likely to vote for options that appear first on the list).
If there's a way to do this within the template itself, that'd be great, but it seems more likely that I'd need to do something in the backend in views.py. I've already tried this, to no effect:
class DetailView(generic.DetailView):
model = Survey
...
def get_context_data(self, **kwargs):
context = super(DetailView, self).get_context_data(**kwargs)
...
survey = get_object_or_404(Survey, survey_link__iexact=survey_link)
...
if randomize_choice_order:
survey.choice_set.order_by('?')
...
return context
Any idea how I can accomplish this? Maybe I need to instead develop a JS function to randomize the objects after they've already been placed?
You can create a custom template tag to shuffle your results.
# app/templatetags/shuffle.py
import random
from django import template
register = template.Library()
#register.filter
def shuffle(arg):
aux = list(arg)[:]
random.shuffle(aux)
return aux
Then in your template
{% load shuffle %}
{% for choice in survey.choice_set.all|shuffle %}
With Django 1.7+ you can use the Prefetch object:
survey = get_object_or_404(
Survey.objects.prefetch_related(
Prefetch('choice', queryset=Choice.objects.order_by('?'),
to_attr='random_choices')
),
survey_link__iexact=survey_link
)
You can then access the random set with survey.random_choices. The original choice set is still available with survey.choice_set.all().

Django get current view in template

How can I get the full name of the current view (my_app.views.index) in a template in Django 1.5?
With forms, I have an object called "view" in the template which I read using a template tag.
But with DetailViews I doesn't see anything similar.
Is there a way using a custom template processor?
Thanks
EDIT
Situation 1:
I retrieve a page, for example '/foo/bar/5/edit'.
Django will call 'foo.views.editbar' with pk=5.
This view renders an template 'foo/bar_form.html'
Situation 2:
If I retrieve '/foo/bar/new'
Django will call 'foo.views.newbar'
This view renders the same template as above ('foo/bar_form.html')
How can I check in this template 'foo/bar_form.html', from which view it has been rendered?
The result should be one of
'foo.views.editbar'
'foo.views.newbar'
Type just in view
{% with request.resolver_match.view_name as view_name %}
...
{{ view_name }}
...
{% endwith %}
I'm not sure I completely understand the requirement, but take a look at inspect.stack.
inspect.stack()[1][3]
Just set attribute to request object in view:
setattr(request, 'view', 'app.views.func')
and check this in template:
{% if request.view == 'app.views.func' %}
do something
{% endif %}
It worked for me.

Compare attributes of a Django Queryset in a template using the `in` Operator

I'm trying to use the in operator to determine if a template variable on the current page is also a foreign key in another model.
The model is like so:
class WishlistItem(models.Model):
user = models.ForeignKey(User, related_name='wishlist_items')
issue = models.ForeignKey(Issue)
On the "Issue" page template, I'm trying to do this:
{% if issue in user.wishlist_items %}
{% else %}
{# A button to add the issue to the user's wishlist #}
{% endif %}
What I need to do is to get at the issue attribute of the wishlist_items QuerySet for the currently logged-in user and compare it to the issue object of the current page. I'm at a loss for how to do this. Do I need to write a templatetag to do this?
I ended up solving this by writing a template filter:
#register.filter
def in_list(obj, arg):
"Is the issue in the list?"
return obj in (item.issue for item in arg)
Then I could do something like this in a template:
{% if issue|in_list:user.wishlist_items.all %}
I got the idea from the answer on this Stack Overflow question.
It seems that there's a relationship between User and wishlist issues that you ought to express as a ManyToManyField on the User. If there is extra metadata about the relationship that you need to record in a WishlistItem, then use through=WishlistItem.
If the User model is from the auth app, you'll need to extend the User model to achieve this (see this blog post for some help). For example:
class MyUser(User):
wishlist_issues = models.ManyToManyField(Issue, through=WishlistItem)
# ...
Then, in your template use:
{% if issue not in user.wishlist_issues %}
{# A button to add the issue to the user's wishlist #}
{% endif %}
wishlist_items is not a queryset - it's a manager. wishlist_items.all IS a queryset, but obviously it is a queryset of WishlistItem objects, not Issue objects. What I would do is handle this logic in the view... something like:
user_has_issue = issue in (wl.issue for wl in request.user.wishlist_items.all())
If I understood correctly, instead of writing a templatetag for it you can pass that as a parameter of the view.
def myView(request):
return render_to_response('template.html',
{'query': queryToCheckIfIssueInWishList},
RequestContext(request))
I think what you are refering to should go into the view, more than the template.
Of course, you could create some templatetag, however Django's approach to templates is to maintain them as dumb as possible, and move all logic to the view.
On the other hand, moving the logic in the view, and then passing the additional information to the template should be quite straightforward, and I would definitely go for that solution.

Categories