How to change template based on user authentication in django - django

If user successfully login i need to show one template. if user not login i need to show another template.
I created two templates one is base.html another one is base_login.html template.
IF user successfully login i need to call base_login.html other wise base.html. i am using below to achieve this. it's not giving expected result. How do achieve this?
{% if user.is_authenticated %}
<p>Welcome {{ user.username }} !!!</p>
{% extends "base_login.html" %}
{% else %}
{% extends "base.html" %}
{% endif %}

If your template goes invalid, I suggest you to it at the views.py, an example:
from django.shortcuts import render, render_to_response
def homepage(request):
template_name = 'homepage.html'
extended_template = 'base_login.html'
if request.user.is_authenticated():
extended_template = 'base.html'
return render(
request, template_name,
{'extended_template': extended_template, ...}
)
# homepage.html
{% extends extended_template %}
{% block content %}
{% if request.user.is_authenticated %}
Hello {{ request.user }}
{% endif %}
{% endif %}
Note: if function of render still doesn't work well, please try with render_to_response such as this answer: https://stackoverflow.com/a/1331183/6396981

Related

Using Checkbox in ListView

I'm trying to make Todo app. I want to make checkbox next to task, so when you select it, the task is set to done. The problem is, I can't really know how to change value of my BooleanField in Task Model. There are plenty of posts like this, but they are usually using functions inside views.py or use forms, but I can't relate do my form in ListView.
views.py
class TodolistView(LoginRequiredMixin, ListView):
model = Todolist
template_name = 'todolist.html'
def get_queryset(self):
return Todolist.objects.all().filter(user=self.request.user)
def get(self, request, *args, **kwargs):
todolist_objects = Todolist.objects.all()
return render(request, 'todolist.html', {'todolist_objects': todolist_objects})
todolist.html
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<p>Add new task</p>
{% for todo in todolist_objects %}
<div>
<form action="" method="post">
<li> {{ todo }} see details</l>
</form>
</div>
{% endfor %}
{% endblock %}

How to dynamically call a Django templatetag from a variable

I'm trying to allow for dynamic template tags. Specifically, I have a menu setup that I'm defining in code vs templates. And I would like to render the menu label as {{ request.user }}. So how can I define that as a string in Python, and allow the template to parse and render the string as intended. And not just variables too, templatetags as well ({% provider_login_url 'google' next=next %}).
What am I missing?
Update with code:
I'm specifically designing my menus with django-navutils, but that's less important (basically the package just stores the defined data and then uses templates to render it).
from navutils import menu
top_horizontal_nav = menu.Menu('top_nav')
left_vertical_nav = menu.Menu('left_nav')
menu.register(top_horizontal_nav)
menu.register(left_vertical_nav)
sign_in = menu.AnonymousNode(
id='sign_in',
label='Sign In',
url='{% provider_login_url "google" next=next %}',
template='nav_menu/signin_node.html',
)
user = menu.AuthenticatedNode(
id='user_menu',
label='{{ request.user }}',
url='#',
template='nav_menu/username_node.html'
)
top_horizontal_nav.register(sign_in)
top_horizontal_nav.register(user)
What I would like to do, is now render these string values ('{{ request.user }}') in my templates
{% load navutils_tags %}
<li
class="{% block node_class %}nav-item menu-item{% if node.css_class %} {{ node.css_class }}{% endif %}{% if is_current %} {{ menu_config.CURRENT_MENU_ITEM_CLASS }}{% endif %}{% if has_current %} {{ menu_config.CURRENT_MENU_ITEM_PARENT_CLASS }}{% endif %}{% if viewable_children %} has-children has-dropdown{% endif %}{% endblock %}"
{% for attr, value in node.attrs.items %} {{ attr }}="{{ value }}"{% endfor %}>
<a href="{{ node.get_url }}" class="nav-link"{% for attr, value in node.link_attrs.items %} {{ attr }}="{{ value }}"{% endfor %}>{% block node_label %}{{ node.label }}{% endblock %}</a>
{% if viewable_children %}
<ul class="{% block submenu_class %}sub-menu dropdown{% endblock %}">
{% for children_node in viewable_children %}
{% render_node node=children_node current_depth=current_depth|add:'1' %}
{% endfor %}
</ul>
{% endif %}
</li>
So, for the above, where I'm rendering {{ node.label }}, how can I get the value stored in node.label to actually be parsed as a request.user? This similarly applies for the URL of value {% provider_login_url "google" next=next %}.
You can create a custom template tag and render those. Like this
from django import template
register = template.Library()
#register.simple_tag(takes_context=True)
def render_nested(context, template_text):
# create template from text
tpl = template.Template(template_text)
return tpl.render(context)
Then in template
...
<a href="{{ node.get_url }}" class="nav-link"
{% for attr, value in node.link_attrs.items %} {{ attr }}="{{ value }}"{% endfor %}>
{% block node_label %}{% render_nested node.label %}{% endblock %}
</a>
...
Haven't tested but I think it will work.
More on template: https://docs.djangoproject.com/en/dev/ref/templates/api/#rendering-a-context
More on custom tags: https://docs.djangoproject.com/en/dev/howto/custom-template-tags/#writing-custom-template-tags
If I understand you well, you want to write template code that renders to template code and then be processed again. Something like ... meta-templates?
I can see you already figured out the first part, but now you need the resulting code to be parsed again in order to set the respective value for {{ request.user }}.
I achieve that by using middleware, but since parsing a template is an expensive operation I implemented some a mechanism to apply the "re-parsing" process just to urls/views of my selection.
The model.
class ReparsingTarget(models.Model):
url_name = models.CharField(max_length=255)
Simple enough, just a model for storing those URL names I want to be affected by the middleware.
The middleware.
class ReparsingMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# We are no interested in whatever happens before
# self.get_response is called.
response = self.get_response(request)
# Now we will re-parse response just if the requested url
# is marked as target for re-parse.
if self._marked(request) and isinstance(response, TemplateResponse):
# Decode the template response code ...
content = response.content.decode('utf-8')
# Create a Template object ...
template = Template(content)
# Provide request to de context ...
context_data = response.context_data
context_data.update({'request': request})
# ... and renders the template back the the response.
response.content = template.render(Context(response.context_data))
return response
def _marked(self, request):
url_name = resolve(request.path_info).url_name
return ReparsingTarget.objects.filter(url_name=url_name).exists()
It is a really simple implementation, the tricky part for me was to figure out how to put the idea into Django code.
In practice.
Some model.
class Foo(models.Model):
label = models.CharField(max_length=255)
The template:
{% for foo in foos %}
{% comment %} Remember foo.label == '{{ request.user }}' {% endcomment %}
<p> Username: {{ foo.label }} </p>
{% endfor %}
The stored Foo instance:
And the result:

Boolean check inside a for loop in a Django template

In a Django template I have the following for loop
{% for document in documents %}
<li>{{ document.docfile.name }}</li>
{% endfor %}
Through this loop I am showing the user all the uploaded files of my app.
Now say that I want to show the user only the files he/she has uploaded.
I have the current user in the variable {{ request.user }}
and also I have the user who did the i-th upload in {{ document.who_upload }}
My question is how can I compare these two variables inside the loop to show only the uploads that have a who_upload field that of the current user?
For example I tried the syntax
{% if {{ request.user }} == {{ document.who_upload }} %}
{% endif %}
but it does not seem to work.
What is the proper syntax for this check?
Thank you !
This should get the job done:
{% if request.user.username == document.who_upload.username %}
{% endif %}
But you should consider performing this logic in your view. This is assuming you're not looping over the entire queryset anywhere else.
views.py
========
from django.shortcuts import render
from .models import Document
def documents(request):
queryset = Document.objects.filter(who_upload=request.user)
return render(request, 'document_list.html', {
'documents': queryset
})
A better option would be to compare the users' primary keys, instead of comparing user objects, which most definitely will be different.
{% if request.user.pk == document.who_upload.pk %}
<span>You uploaded this file</span>
{% endif %}

Django Include Not Including Content

I want to use {% include %} to include a second form on a page, but the form is empty..
views.py:
def year_form(request):
thing_list = Thing.objects.all()
if request.method == 'POST':
form = YearBrowseForm(request.POST)
if form.is_valid():
year = form.cleaned_data['year']
return HttpResponseRedirect(reverse('browse_years', kwargs={'year':year}))
else:
form = YearBrowseForm()
return render(request, 'browse-year.html', {'form':form, 'thing_list':thing_list})
forms.py:
class YearBrowseForm(forms.Form):
year = forms.ChoiceField(choices=YEARS_EMPTY, widget=forms.Select(attrs={'onchange': 'this.form.submit();'}))
url:
url(r'^browse/years/(?P<year>\d+)/$', 'my_app.views.browse.year_form', name='browse_years'),
html:
{% extends 'base.html' %}
{% block content %}
{% include 'browse-year.html' %}
{% endblock %}
browse-year.html:
<form action='' method='post' enctype='multipart/form-data'>
{{ form.as_p }}
{% csrf_token %}
</form>
This renders an empty form (i.e. the source shows that a form is being included, but it is empty of content). What am I missing here? This is a continuation of this question that I am trying to solve in a different method by using {% include %}. Thanks for your ideas!
This happens because you are rendering browse-year.html:
return render(request, 'browse-year.html', {'form':form, 'thing_list':thing_list})
You should be rendering the other html, the one you didn't gave a name, but starts with
{% extends 'base.html' %}
only by rendering that one you extend the base, and the other content appears.

Django isn't finding my objects

I'm running through the django tutorial, and built the sample polls app. I've got 5 polls in the system, visible through the admin interface to me. However, my rudimentary index view and template don't seem to display them(instead, the template defaults to the else clause as if there were no polls).
My index view is as follows:
def index(request):
latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5]
return render_to_response('index.html', {'latest_poll_list': latest_poll_list})
And the template index.html:
{% if latest_poll_List %}
<ul>
{% for poll in latest_poll_list %}
<li>{{ poll.question }}</li>
{% endfor %}
</ul>
{% else %}
<p> No polls are available.</p>
{% endif %}
I can even do polls = Poll.objects.all() (with or without order_by and the truncation) in the manage.py shell, and it returns everything fine. What gives?
It could be a simple typo: latest_poll_List should be latest_poll_list with a lower case L on the list. Otherwise maybe try:
{% if latest_poll_list.count > 0 %}
...
{% endif %}
Also try:
{{ latest_poll_list }}
in your template somewhere to see if it prints out the correct list of objects (i.e. the template is getting the correct list of polls)