active Navbar BOOTSTRAP v4 - python

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']}>

Related

Wagtail modeltranslation language switcher doesn't work on /search page

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.

how to do ajax pagination in Django?

!! 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>

Django dropdown filter with ajax?

I need to update my template when the user chooses a value of the dropdown list. Is there a possibility to do this with an ajax call or similiar? It would be perfect that if the user is selecting a value of the dropdown, this value would be send to my view and the content in my page would update without page refresh.
I tried different things but nothing worked... Any suggestion is welcome.
Here's my shortened code:
models.py
class Author(models.Model):
id = models.IntegerField(primary_key=True)
author = models.CharField(max_length=50)
status = models.CharField(max_length=50)
[...]
views.py
def authors(request):
authors = Author.objects.all()
if request.method="GET":
authors = Author.objects.filter(status = filter)
template
<div class="dropdown">
<button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Choose status
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
<a class="dropdown-item" href="#">Staff</a>
<a class="dropdown-item" href="#">Admin</a>
[...]
</div>
</div>
{% for author in authors %}
{{author.author}}
{% endfor %}
template
<a class="dropdown-item" href="{% url 'admin' %}">Staff</a>
<a class="dropdown-item" href="{% url 'staff' %}">Admin</a>
urls.py
url(r'^admin/', authors_admin, name='admin'),
url(r'^staff/', authors_staff, name='staff'),
views.py
def authors_admin(request):
authors = Author.objects.all()
if request.method="GET":
authors = Author.objects.filter(status = 'admin')
return render(request, 'template.html', {
'authors ': authors
})
def authors_staff(request):
authors = Author.objects.all()
if request.method="GET":
authors = Author.objects.filter(status = 'staff')
return render(request, 'template.html', {
'authors ': authors
})

Associate multiple unique forms to a unique object in Django

I'm trying to build a web application using Django where a user can create a 'Project' and within that 'Project', there are four different forms.
My Question is, how do I associate those forms to a specific 'project' in the sense that the form is linked to that specific 'project'.
I'm close to doing it but I'm having issues with the 'create-project.html', 'create-request-1.html' and 'create-request-2.html' pages from rendering due to the 'PK' in the 'projects.html' page URL.
The exact errors I get for navigating to those pages is -
NoReverseMatch at /projects/create-project/
Reverse for 'initiate_project' with no arguments not found. 1 pattern(s) tried: ['projects\\/project\\/(?P<pk>[0-9]+)\\/$']
Or
NoReverseMatch at /project/create-post-1/
Reverse for 'initiate_project' with no arguments not found. 1 pattern(s) tried: ['projects\\/project\\/(?P<pk>[0-9]+)\\/$']
The path is as follows -
'projects.html' -
'create-project.html' -
'initiate-project.html' -
'create-request-1.html'
'create-request-2.html'
I can navigate and go into each unique 'project' (e.g. project 1, project 2) in 'projects.html' but I can't get into my forms ('create-request-1.html', 'create-request-2.html') inside the 'initiate-project.html' page that's within each 'project' in the 'projects.html' page.
Here's my code so far -
model.py -
from django.db import models
class create_new_project(models.Model):
list_display = ('project_name', 'project_manager',
'technical_lead', 'test_lead')
class Meta:
verbose_name = 'Create New Project'
verbose_name_plural = 'Create New Projects'
project_name = models.CharField(max_length=100)
project_manager = models.CharField(max_length=100)
technical_lead = models.CharField(max_length=100)
test_lead = models.CharField(max_length=100)
environment_choices = (
('1', '1'),
('2', '2'),
('3', '3')
)
environment = models.CharField(
max_length=50, choices=environment_choices, default='ICCS')
def __str__(self):
return self.project_name
views.py
from django.shortcuts import render
from django.shortcuts import render, get_object_or_404
from main.models import *
# Create your views here.
def index(request):
return render(request, 'main/index.html')
def projects(request):
CreateNewProject = create_new_project.objects.all()
args = {'CreateNewProject': CreateNewProject}
return render(request, 'main/projects.html', args)
def create_project(request):
return render(request, 'main/create-project.html')
def initiate_project(request, pk):
InitiateProjectURL = get_object_or_404(create_new_project, pk=pk)
return render(request, 'main/initiate-project.html', {'InitiateProjectURL': InitiateProjectURL})
def create_post_request_1(request):
return render(request, 'main/create-post-request-1.html')
def create_post_section_2(request):
return render(request, 'main/create-post-request-2.html')
urls.py
from django.urls import include, path
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('projects/', views.projects, name='projects'),
path('projects/create-project/', views.create_project, name='create_project'),
path('projects/project/<int:pk>/',
views.initiate_project, name='initiate_project'),
path('project/create-post-request-1/',
views.create_post_request_1, name='create_post_paid_request_section_1'),
path('project/create-post-request-2/',
views.create_post_request_2, name='create_post_request_2'),
]
projects.html
<div class="row">
<a href="{% url 'create_project' %}" class="card card-1 bg-red shadow m-2">
<div class="card-body d-flex h-100">
<div class="text-center mx-auto justify-content-center align-self-center">
{% load staticfiles %}
<img src="{% static 'main/images/plus.svg' %}" alt="Plus Icon" height="60vh">
<div class="mb-3 pt-4 text-white">Create New Project</div>
</div>
</div>
</a>
{% for create_new_project in CreateNewProject %}
<div class="card card-1 bg-white shadow m-2">
<div class="card-body">
<h4 class="card-title text-red">{{ create_new_project.project_name }}</h4>
<div class="card-text pt-2 pb-2">
<div class="mb-3"><b>Project Manager: </b>{{ create_new_project.project_name }}</div>
<div class="mb-3"><b>Project Lead: </b>{{ create_new_project.project_manager }}</div>
<div class="mb-3"><b>Test Lead: </b>{{ create_new_project.test_lead }}</div>
<div class="mb-3"><b>Environment: </b>{{ create_new_project.environment }}</div>
</div>
<div class="float-right">
<a href="{% url 'initiate_project' pk=create_new_project.pk %}" class="text-red">
{% load staticfiles %}
<img src="{% static 'main/images/next.svg' %}" class="text-red" alt="Next Icon" height="25vh"></a>
</div>
</div>
</div>
{% endfor %}
</div>
create-post-request-1.html / create-post-request-2.html
<div class="col-md-2">
Cancel
</div>
To better illustrate what I'm trying to do, See the following image - Visual description
the href for the a tag in create-post-request-1.html / create-post-request-2.html should be sth like "{% url 'initiate_project' pk=any_pk_you_choose %}" instead of {% url 'initiate_project' %}

Django user authentication working properly EXCEPT 1 view/template

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.

Categories