How to render common things in footer.html in Django - python

I have set up Django templates, which include index.html, header.html and footer.html.
In footer.html, I want to set dynamically a phone number, email and address. I can see I can pass it through context from views.py, but footer.html will included in all the templates, so I will need to pass it in every function in views.py, which is not good.
So what I want is to create one common function and I want to call it from footer.html. Is that the right way to do this? Or if you have any other idea, then please let me know how to do that.
views.py:
def index(request):
portal_contact_email = preferences.MyPreferences.portal_contact_email
context = {'portal_contact_email': portal_contact_email,}
return render(request, 'mysite/index.html', context)
footer.html:
<footer class="bg-dark footer-section">
<div class="section">
<div class="container">
<div class="row">
<div class="col-md-4">
<h5 class="text-light">Email</h5>
<p class="text-white paragraph-lg font-secondary">{{ portal_contact_email }} </p>
</div>
<div class="col-md-4">
<h5 class="text-light">Phone</h5>
<p class="text-white paragraph-lg font-secondary"></p>
</div>
<div class="col-md-4">
<h5 class="text-light">Address</h5>
<p class="text-white paragraph-lg font-secondary"></p>
</div>
</div>
</div>
</div>
<div class="border-top text-center border-dark py-5">
<p class="mb-0 text-light">Copyright #<script>
var CurrentYear = new Date().getFullYear()
document.write(CurrentYear)
</script>
{# a theme by themefisher.com#}
</p>
</div>
</footer>

For this purpose you could create a custom ContextProcessor.
According to the docs, ContextProcessors
take a request object as their argument and return a dictionary of items to be merged into the context
A custom ContextProcessor in your case could look like this:
def footer_data(request):
return {'phone_number': 'xyz', ...}
Then append it to your settings.py so it is actually being used:
TEMPLATES = [
{
...
'OPTIONS': {
'context_processors': [
'myapp.my_context_processors.footer_data',
...
And in your templates you can access these variables simply with {{ phone_numer }}.

Related

Django: For each loop with counter that loads queryset in small sets

I am building an online store that displays cards containing products passed into the template as a queryset. The list of products will get large so I want to implement an incremental load that starts with 10 products and there is a button to load 10 more... and that would continue until eventually all the products are displayed. I currently have a for each loop in the template and I was wondering what the best approach would be to add some sort of counting mechanism into the loop so that I am able to achieve the incremental load.
Any idea how I can do this?
views.py
def products_page_all(request):
resetDefaultFilters()
products = Product.objects.order_by('?')
args = {
'products': products,
}
return render(request, 'store/products-page.html', args)
products-page.html
...
{% for product in products %} <-- I want this to only iterate for 10 products at a time
<a href="{% url 'store-view-item' product.product_id %}">
<div class="col-lg-3 col-md-4 col-sm-6 col-xs-4 my-auto">
<div class="card h-100 rounded-0 border-0">
<div class="img-wrapper">
<div class="image">
<img src="{{ product.product_image.url }}">
</div>
</div>
<div class="card-body text-center">
<h4 class="card-title">
<a id="product-name">{{ product.product_name }}</a>
</h4>
<p id="seller-name">// {{product.seller.seller_listing_name }} //</p>
<p class="card-text" id="product-description">{{ product.description_short }}</p>
<h5 id="product-price">${{ product.price | floatformat:2 }}</h5>
</div>
</div>
</div>
</a>
{% endfor %}
<button>LOAD MORE</button> <-- this button should load the next 10 products
In order to find the "next 10", you'll either need the products in some fixed order, or explicitly exclude the products that you've already shown.
You can use [:10] or [0:10] to get the first ten products, [10:20] to get the next ten, and so on.
Something like either (a):
products = (
Product.objects
.order_by('id')
[start : start + 10]
)
Or, (b):
products = (
Product.objects
.exclude(id__in=already_shown)
.order_by('?')
[:10]
)
The button will need to make an AJAX call to retrieve the next set of products, keeping track of either the start or the already_shown variables.

How to dynamically re-render template?

Currently I am trying to create a dynamic filter for listing model objects in a template. Here is the django view:
def view_data(request):
text = request.GET.get('text')
persons = None
if text:
try:
persons = models.Person.objects.get(code__regex=text)
except models.Person.DoesNotExist:
pass
return render(request, 'view_data.html',
{'persons': persons if not isinstance(persons, models.Person) else [persons]})
The related part from the template:
<div class="jumbotron row">
<form>
<label>Alanyok szűrése</label>
<input id="filter" type="text" placeholder="Keresett alany">
</form>
</div>
<div class="row">
<div class="col-4">
<div class="list-group" id="list-tab" role="tablist">
{% for person in persons %}
<a class="list-group-item list-group-item-action" id="list-{{person.code}}" data-toggle="list" href="#" role="tab" aria-controls="{{person.code}}">{{person.code}}</a>
{% endfor %}
</div>
</div>
<div class="col-8">
<div class="visualisation content">
<div class="canvas_div">
<canvas id="Canvas1" width="540" height="250" style="border:1px solid #202020;">
</canvas>
</div>
</div>
</div>
</div>
The input field with filter id has a callback on keyup event which sends a request to django with the content of the input field which is used in the view for query.
Here is the callback:
$( "#filter" ).keyup(function() {
$.get("", {text: $('#filter').val()});
});
When I checked it with Pycharm debugger, the render returns the correct html but on the client side the html doesn't change. How to re-render with the new object list?
Take a part of your html code that you want to replace and place it inside a new html file like this:
new_html:
<div class="list-group" id="list-tab" role="tablist">
{% for person in persons %}
<a class="list-group-item list-group-item-action"
id="list-{{person.code}}" data-toggle="list"
href="#" role="tab" aria-controls="{{person.code}}">
{{person.code}}
</a>
{% endfor %}
</div>
now in your view replace the name of your old html file ( that you are rendering ) with the new html file like this:
return render(request, 'new_html.html',
{'persons': persons if not isinstance(persons,models.Person) else [persons]})
and now in your ajax you can dynamically load this new_html like this :
$( "#filter" ).keyup(function() {
$.get("",
{text: $('#filter').val()},
function(data){
$( "#list-tab" ).replaceWith( data );
}
);
});
You are not doing nothing with the returned data. Add a callback function in the get method call. You get the response from the server in the first argument. Use that to hide and show contents on the page. Or you can even replace elements in the DOM. See jquery.replaceWith.
$( "#filter" ).keyup(function() {
$.get("", {text: $('#filter').val()}, function(response){ });
});

passing a parameter from html page url mapping to the views in django

front.html
<div class="row">
<a href="{% url 'emp_pay_list' Information_technology %}">
<div class="col-md-6 col-sm-6 col-lg-3">
<div class="dash-widget clearfix card-box" style="height: 200px;">
<span class="dash-widget-icon"><i class="fa fa-cubes" aria-hidden="true"></i></span>
<div class="dash-widget-info">
<h3>20</h3>
<span>Information Technology</span>
</div>
</div>
</div>
</a>
<a href="{% url 'emp_pay_list' sales %}">
<div class="col-md-6 col-sm-6 col-lg-3">
<div class="dash-widget clearfix card-box" style="height: 200px;">
<span class="dash-widget-icon"><i class="fa fa-users" aria-hidden="true"></i></span>
<div class="dash-widget-info">
<h3>7</h3>
<span>Sales Team</span>
</div>
</div>
</div>
</a>
</div>
The above code is the front end part HTML here I want to pass a parameter into the urls.py by clicking a box and depends on the parameter which we pass the data should be fetched.
urls.py
url(r'^list_of_employees/<string>/$', views.Pay_slip_list , name='emp_pay_list'),
This is the code which I am using in urls.py to pass parameter.
views.py
def Pay_slip_list(request, department):
hello = employees.objects.select_related('employee_name', 'employee_auth').filter(department=department)
return render(request, 'hr/emp_pay_list.html', {'hello': hello})
And this is the views.py part where I am fetching data from the database based on the string/parameter passed after clicking the box.
Your URL pattern must look like
from django.urls import path, re_path
path('list_of_employees/<str:department>/', views.Pay_slip_list , name='emp_pay_list'),
or use re_path
re_path(r'^list_of_employees/(?P<department>[\w\-]+)/$', views.Pay_slip_list , name='emp_pay_list')
use path instead of url for Django version >= 2.0, or use re_path for complex patterns, re_path is same as url method in lower versions

Links that I have in 'navbar' overlaps each other:/

Hello everyone:) Links that I have in 'navbar' overlaps each other when I make a transition into another link. For instance, I have a navbar menu with four different links (home, catalog, distributors and contacts) and 'home' is a base webpage. I.e when I make a transition from the base webpage 'http://127.0.0.1:8000/' to catalog I get this http://127.0.0.1:8000/catalog (all right) but then I make a transition into section 'distributors' and then I get this 'http://127.0.0.1:8000/catalog/distributors (and it's not normal) How to rectify this?
My url patterns seems right :/
urlpatterns = [
url(r'^$', views.home, name='home'),
url(r'^catalog/$', views.catalog, name='catalog'),
url(r'^distributors/$', views.distributors, name='distributors'),
url(r'^contacts/$', views.contacts, name='Contacts'),
]
template:
<div class="header">
<div id="inner">
<div class="col">
<div class="inner">
<div class="image"><p>HOME</p></div>
<div class="filter1"></div>
<div class="filter2"></div>
<div class="txt">
<p>We greet you on the main</p>
<p>page of our website!</p>
</div>
</div>
</div>
<div class="col">
<div class="inner">
<div class="image"><p>CATALOG</p></div>
<div class="filter1"></div>
<div class="filter2"></div>
<div class="txt">
<p>Browse through our catalog</p>
<p>and select the good just for you.</p>
</div>
</div>
</div>
<div class="col">
<div class="inner">
<div class="image"><p>DISTRIBUTORS</p></div>
<div class="filter1"></div>
<div class="filter2"></div>
<div class="txt">
<p>We are currently expanding our</p>
<p>distributor network into new markets.</p>
</div>
</div>
</div>
<div class="col">
<div class="inner">
<div class="image"><p>CONTACTS</p></div>
<div class="filter1"></div>
<div class="filter2"></div>
<div class="txt">
<p>You can always communicate with us</p>
<p>using section "Contacts". </p>
</div>
</div>
</div>
</div>
</div>
views:
def home(request):
products_images = ProductImage.objects.filter(is_active=True, is_main=True, product__is_active=True)
products_images_with = products_images.filter(product__category__id=1)
products_images_without = products_images.filter(product__category__id=2)
return render(request, 'landing/home.html', locals())
def catalog(request):
products_images = ProductImage.objects.filter(is_active=True, is_main=True, product__is_active=True)
return render(request, 'landing/catalog.html', locals())
def distributors(request):
return render(request, 'landing/distributors.html', locals())
def contacts(request):
return render(request, 'landing/Contacts.html', locals())
Can someone help me with this problem? Django version 1.11.2
As #David D. answered, you should use the method of url building as it provides you flexibility.
But, if for some reason you want that absolute URLs should be specified in href, then while using absolute urls the above problem can be solved by prepending a forward slash to each url name when assigning to href.
So your new urls should look like :
CATALOG
DISTRIBUTORS
CONTACTS
The reason it works is that / represents root of website, so using '/' routes you to the root and using '/catalog' routes you to the catalog page directly from the root.
The problem is the way you use links in your Django templates.
Take a look to: https://docs.djangoproject.com/en/2.0/ref/templates/builtins/#url
You have to use a {% url 'url-name-here' %} sothat Django will build url by itself.
For example, in your case:
<div class="image"><p>CATALOG</p></div>
This way:
it's a lot easier for you, you just provide the url name and let Django generated the real url.
you don't repeat yourself; if you want to change the path of the url, you only need to do it one time in urls.py.

Send data from django views to angularjs controller

I am trying to send data from django views.py file to angularjs controller.js file but unable to send it.
The problem is this that I am unable to send data from views file to controller. And when I run my code then the value {%steps%} doesn't change to the value I have assigned in views file.
I don't want to use Django rest framework for doing this.
Is there any other way of achieving this? If yes, then please help me out.
views.py:
from django.shortcuts import render
from django.conf import settings
from user_data.models import GetData
import json
def home(req):
return render(req, 'index.html')
def userData(req):
if req.method == 'GET':
user_data = GetData().getAllData()
context_dict = {'user_data1' : json.dumps(user_data[0]),
'user_data2' : json.dumps(user_data[1]),
'user_steps' : json.dumps(2000)}
return render(req, 'index.html', context_dict)
controller.js :
'use strict';
MetronicApp.controller('DashboardController', function($rootScope, $scope, $http, $timeout) {
$scope.$on('$viewContentLoaded', function() {
// initialize core components
Metronic.initAjax();
});
$scope.steps = {{user_steps|safe}};
});
html file:-
<div ng-controller="DashboardController" class="margin-top-10">
<div class="row ">
<div class="col-md-12 col-sm-12">
<div class="portlet light ">
<div class="portlet-title">
<div class="caption">
<i class="icon-cursor font-purple-intense hide"></i>
<span class="caption-subject font-purple-intense bold uppercase">Tracker Report</span>
</div>
<div class="actions">
<a href="javascript:;" class="btn btn-sm btn-circle btn-default easy-pie-chart-reload">
<i class="fa fa-repeat"></i> Reload </a>
</div>
</div>
<div class="portlet-body">
<div class="row">
<div class="col-md-3">
<div class="easy-pie-chart">
<div class="number transactions" data-percent="55">
<span>{$ steps $}</span>
</div>
<!-- <a class="title" href="#"> -->
Steps <!-- <i class="icon-arrow-right"></i> -->
</a>
</div>
</div>
<div class="margin-bottom-10 visible-sm">
</div>
<div class="col-md-3">
<div class="easy-pie-chart">
<div class="number visits" data-percent="85">
<span>
+85 </span>
%
</div>
<!-- <a class="title" href="#"> -->
Sleep<!-- <i class="icon-arrow-right"></i> -->
</a>
</div>
</div>
<div class="margin-bottom-10 visible-sm">
</div>
<div class="col-md-3">
<div class="easy-pie-chart">
<div class="number bounce" data-percent="46">
<span>
+46 </span>
%
</div>
<!-- <a class="title" href="#"> -->
Calories <!-- <i class="icon-arrow-right"></i> -->
</a>
</div>
</div>
<div class="margin-bottom-10 visible-sm">
</div>
<div class="col-md-3">
<div class="easy-pie-chart">
<div class="number bounce" data-percent="32">
<span>
+32 </span>
%
</div>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
This is basically what I have done in one of my major django projects (but I am not 100% sure, whether this is or this ain't what you are looking for, as an answer).
So, instead of views.py, I have made a custom.py file in which I make custom APIs and call them (using urlpatterns) in the urls.py of my django app. And I have another set of APIs for which I am using django rest framework, for which I make viewsets rather than simple views. Just in case, you are interested, you might like reading this SO link.
But since, you specifically mentioned that you don't want to use django rest frameworks, I will give you an example of the custom.py file, as mentioned above.
Below you will find a sample of an API defined in a custom.py,
#api_view(['GET'])
def get_user_details(request):
"""
API View that gives a user detail
---
parameters:
- name: email
description: The email of the user based on which his/her information has been extracted
required: true
type: string
responseMessages:
- code: 400
message: Email required as GET parameters.
message: User not found.
- code: 200
mesage: User details sent successfully
consumes:
- application/json
- application/xml
produces:
- application/json
- application/xml
"""
email = request.query_params.get('email', None)
if email is None:
return HttpResponseBadRequest("Email required as GET parameters.")
try:
user = User.objects.get(username=email)
except User.DoesNotExist:
return HttpResponseBadRequest("User not found.")
response_data = {'id': user.id, 'first_name': user.first_name, 'last_name': user.last_name,}
return HttpResponse(json.dumps(response_data), content_type="application/json")
And subsequently, the urls.py in my django app looks like:
urlpatterns = router.urls
urlpatterns = urlpatterns + [
url(r'get_user_details/', get_user_details),
]
My controller would look something like this:
CheckEmail : function (current) {
return $http({
method: 'GET',
url: baseAPI + 'admin/get_user_details/',
params: {email: current},
})
},
And then subsequently, you may be able to render the variable you wish to print in your html file using handles.
Hope, it helps.

Categories