I am working with Django 1.11.5 and logging-in and validating users via Social Auth.
The user authentication, log-in and logoff are working as expected in 12/13 of my templates. All my templates extend my navbar and footer base.html template.
In 'base.html' I have the following code for the navbar:
{% if user.is_authenticated %}
<li class="nav-item">
<span class="nav-link" id="user-name">{{ request.user.username }}</span>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'logout' %}">Logoff</a>
</li>
{% else %}
<li class="nav-item log-in-link">
<a class="btn btn-primary nav-link log-in" href="{% url 'social:begin' 'google-oauth2' %}"><span>Log-In <i class="fa fa-google-plus" aria-hidden="true"></i></span></a>
</li>
{% endif %}
Now, this navbar code works properly in 12/13 of my templates. It is only for 1 template/view/URL where the user is not authenticated.
I have tried debugging by printing out the user name and information in the template giving me errors but it looks like the user is getting logged out when reaching that template via its URL and view.
I am totally lost.
Could someone point out things I can check/do to debug and locate the source of this logoff error? I can provide the relevant code if needed.
views.py code
def details_request(request, request_data_ID):
data_request_object = DatasetRequest.objects.get(pk=request_data_ID)
user_ID = data_request_object.user.username
has_attributes = False
request_data_attrs = []
if len(data_request_object.attr_names) > 0:
if len(data_request_object.attr_names['names']) > 0:
has_attributes = True
for idx, attr_names in enumerate(data_request_object.attr_names['names']):
request_data_attrs.append([attr_names,
data_request_object.attr_names['descriptions'][idx],
data_request_object.attr_names['types'][idx]])
data_request_detail_template = {
'dataset_request_title': data_request_object.dataset_title,
'dataset_request_description': data_request_object.dataset_description,
'dataset_votes': data_request_object.dataset_votes,
'dataset_date': data_request_object.created_date.strftime("%Y-%m-%d"),
'request_data_ID': request_data_ID,
'has_attributes': has_attributes,
'request_attrs': request_data_attrs,
'user': user_ID,
'is_completed': data_request_object.is_completed
}
data_comment_object = Comments.objects.filter(request_dataset_FK=data_request_object).order_by("-comment_votes")
if len(data_comment_object) > 0:
comment_list = []
for comment_object in data_comment_object:
if comment_object.isComment:
comment_list.append([comment_object.comment, comment_object.created_date.strftime("%Y-%m-%d"), comment_object.comment_votes, comment_object.pk, comment_object.user.username])
data_request_detail_template['comments'] = comment_list
return render(request, "detail_requests.html", data_request_detail_template)
You are specifying:
user_ID = data_request_object.user.username
and put it into context under user key.
In template you have {% if user.is_authenticated %} which means that you are trying to access missing attribute is_authenticated of user.username which always evaluates to False.
Related
I created a templates for header/footer and imports, if I want to acess the username in my header template I cant do that because it has no views. How can I pass the username to the header template?
header_template.py
from django import template
register = template.Library()
#register.inclusion_tag('home/partials/header.html')
def header(element):
return {'element': element, }
Import in Template
{% load header_template %}
{% header context %}
Usage in the template:
{% if user.is_authenticated %}
<a class="btn btn-primary display-4" href="{% url 'home:profil' %}">Profil</a>
{% else %}
<a class="btn btn-primary display-4" href="{% url 'home:login' %}">Login</a>
{% endif %}
Thanks for your help.
You can take context in your tag:
#register.inclusion_tag('home/partials/header.html', takes_context=True)
def header(context, element):
return context | {'element': element}
Read more here:
https://docs.djangoproject.com/en/dev/howto/custom-template-tags/#inclusion-tags
My opinion, you are don't need this, The cause for every new tag in template - a wrong logic.
I have added search url to i18n_patterns, but the language switcher doesn't work on that page.
urls.py:
urlpatterns += i18n_patterns(
path("search/", search_views.search, name="search"),
path("", include(wagtail_urls)),
)
language switcher:
{% get_available_languages_wmt as languages %}
<div class="nav-item dropdown float-right">
<p class="nav-link dropdown-toggle m-auto" data-toggle="dropdown" role="button" aria-expanded="false">
{{ request.LANGUAGE_CODE|upper }}</p>
<div class="dropdown-menu w-25">
{% for language in languages %}
{% if language != request.LANGUAGE_CODE %}
<a class="dropdown-item" href="{% change_lang language page %}">{{ language|upper }}</a>
{% endif %}
{% endfor %}
</div>
</div>
Furthermore, when i add search url above root one the search page raises 404 page.
How can i make the language switcher work on the search page?
The language switcher uses the Wagtail page variable. See the change_lang template tag:
<a ... href="{% change_lang language page %}">...</a>
And search is a Django view, not a Wagtail page. The page variable is not defined.
You can make the switcher work on the search view by setting the href yourself:
{% for language in languages %}
<a href="/{{ language.code }}/search/"
{% endfor %}
Alternatively, you can create a Wagtail search page:
class SearchPage(Page):
def get_context(self, request):
context = super().get_context(request)
... # Copy the code from the current search view.
# Update and return the context
context.update({
'search_query': search_query,
'search_results': search_results,
})
return context
https://docs.wagtail.io/en/latest/topics/pages.html#customising-template-context
You also have to:
Rename (search_page.html) and rework (page.variable_name) your search template.
Remove the search url from urls.py
Add the SearchPage via the Wagtail admin interface to the page tree.
!! I have a model named blog !!
class blog(models.Model):
image = models.ImageField(upload_to='Media/awards')
title = models.CharField(max_length=255,blank=True)
content = models.TextField(blank=True)
and in the frontend I have
<div class="col-md-6" id= "mydiv">
<div>
<!-- pagination design start -->
<div class="blog_bottom_pagination">
<div class="counter">/</div>
<button class="paginate left"><i class="fas fa-angle-left"></i></button>
<button class="paginate right">
<i class="fas fa-angle-right"></i>
</button>
</div>
<!-- pagination design end -->
I don't find any reference how i implement pagination without page refresh and render two data at a time in that div section. and paginate right and left by the button for getting next two data and will replace those previous data in that div.... thank you in advance
So the view side should look like this:
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
blog_objects= Blog.objects.filter()
paginator = Paginator(blog_objects, 10)
page = request.GET.get('page', 1)
try:
blogs = paginator.page(page)
except PageNotAnInteger:
blogs = paginator.page(1)
except EmptyPage:
blogs = paginator.page(paginator.num_pages)
page_list = blogs.paginator.page_range
Button to trigger ajax function on template:
{% for i in page_list %}
<button onclick="ajax_function('{{i}}','{{title}}')">{{i}}</button>
Note "i" is the page number for the ajax function and "title" is the argumant for query.
Ajax function from template is at the end...
Ajax view:
def paginate(request):
page= request.GET.get('page', None)
title= request.GET.get('title', None)
starting_number= (page-1)*10
ending_number= page*10
"here you should multiply the 'page' by the number of results you want per page, in my example it's 10"
result= Blog.objects.filter(title= title)[starting_number:ending_number]
"By [starting_number:ending_number] we specify the interval of results. Order them by date or whatever you want"
data={result}
return JsonResponse(data)
The result object is now sent to the html side, now its time for the ajax function:
function ajax_function(page,title) {
$.ajax({
url: '/ajax/paginate/',
type: "get",
data: {
'page': page,
'title': title,
},
dataType: 'json',
success: function (data) {
$('#id-of-your-choice').empty();
for (i = 0; i < data.result.length; i++) {
$('#id-of-your-choice').append(i)
}
"at first the function cleans the old childs of the element on which you display your results then it appends the new page's content by iterating over 'results'"
Hope that is what you are looking for, have fun!
In Django, the HTML is filled with data before getting served to the end client. So if you want next page data in your front-end code and that too from Django Views then you will have to go to backend again and get the data ant that will require the page to be reloaded.
If you don't want to reload the page then you will have to write APIs using Django Rest Framework. And in the front-end code just use those APIs to navigate between different pages.
Hope this helps!!
First of all in your views.py write this in your view function from which you are rendering this template
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from .models import blog
def your_view_function(request):
blogs = blog.objects.all()
page = request.GET.get('page', 1)
paginator = Paginator(blogs, 5) #number of blogs you want to paginate
try:
blogs = paginator.page(page)
except PageNotAnInteger:
blogs = paginator.page(1)
except EmptyPage:
blogs = paginator.page(paginator.num_pages)
return render(request,'your_html_page.html',{'blogs':blogs}
and in your html page write this most preferred boostrap pagination
<nav aria-label="Page navigation example">
<ul class="pagination justify-content-start mt-3">
{% if not blogs.has_previous%}
<li class="page-item disabled">
<a class="page-link" href="#" tabindex="-1">Previous</a>
</li>
{% endif %}
{% if blogs.has_previous%}
<li class="page-item">
<a class="page-link" href="?page={{blogs.previous_page_number}}" tabindex="-1">Previous</a>
</li>
{% endif %}
{% if blogs.has_previous%}
<li class="page-item"><a class="page-link" href="?page={{blogs.previous_page_number}}">{{blogs.previous_page_number}}</a></li>
{% endif %}
<li class="page-item"><a class="page-link" href="#">{{blogs.number}}</a></li>
{% if blogs.has_next%}
<li class="page-item"><a class="page-link" href="?page={{blogs.next_page_number}}">{{blogs.next_page_number}}</a></li>
{% endif %}
{% if blogs.has_next%}
<li class="page-item">
<a class="page-link" href="?page={{blogs.next_page_number}}">Next</a>
</li>
{% endif %}
{% if not blogs.has_next%}
<li class="page-item disabled">
<a class="page-link" href="#" tabindex="-1">Next</a>
</li>
{% endif %}
</ul>
</nav>
I want to activate link when filtering by category in navbar. But with this code both of this category activates. I think my if statements in HTML working wrong.
search_results.html
<li class="nav-item {% if search_category == BP%}active{% endif%}">
<a class="nav-link" href="{% url 'core:get_category' %}?search_item=BP">Building Products</a>
</li>
<li class="nav-item {% if search_category == BP%}active{% endif%}">
<a class="nav-link" href="{% url 'core:get_category' %}?search_item=OT">Other Products</a>
</li>
method get_category in views.py
def get_category(request):
queryset = Item.objects.all()
search_category = request.GET.get('search_item','')
if search_category:
queryset = queryset.filter(category__icontains = search_category)
context ={
'queryset': queryset
}
return render(request, 'search_results.html', context)
When searching by Building prod
Print(search_category)
BP
Print(search_item)
<QueryDict: {'search_item': ['BP']}>
When searching by Other prod
Print(search_category)
OT
Print(search_item)
<QueryDict: {'search_item': ['OT']}>
I use pagination on scroll by Django EL(Endless) Pagination library in my project.
By default show_more tag show loading word. I want customize it. I use next code but it work incorrect. It show me 9 icons and at the end don't disappear. I am little bit confused. How to fix it?
settings.py:
EL_PAGINATION_LOADING = """<i class='fa fa-cog fa-spin fa-3x fa-fw text-info text-justify endless_loading'>"""
CURRENT SOLUTION:
I found the working solution but I am not sure that its best and clear way to do that.
custom_tags.py:
from django import template
from django.utils.encoding import iri_to_uri
from el_pagination import (settings, utils)
register = template.Library()
#register.inclusion_tag('documents/show_more_info.html', takes_context=True)
def show_more_info(context, label=None, loading=settings.LOADING, class_name=None):
data = utils.get_data_from_context(context)
page = data['page']
if page.has_next():
request = context['request']
page_number = page.next_page_number()
querystring_key = data['querystring_key']
querystring = utils.get_querystring_for_page(
request, page_number, querystring_key,
default_number=data['default_number'])
return {
'label': label,
'loading': loading,
'class_name': class_name,
'path': iri_to_uri(data['override_path'] or request.path),
'querystring': querystring,
'querystring_key': querystring_key,
'request': request,
}
return {}
documents/show_more_info.html:
{% load i18n %}
{% if querystring %}
<div class="endless_container">
<a class="endless_more{% if class_name %} {{ class_name }}{% endif %}" href="{{ path }}{{ querystring }}" data-el-querystring-key="{{ querystring_key }}">
{% if label %}{{ label|safe }}{% else %}{% trans "more" %}{% endif %}
</a>
<div class="endless_loading" style="display: none;">
<div class="alert alert-info infinite-loading text-center">
<i class="fa fa-cog fa-spin fa-3x fa-fw" aria-hidden="true"></i>
</div>
</div>
</div>
{% endif %}
Finally I can use show_more_info tag instead of default show_me tag.