showing dynamic data from database in all views - django

I'm using Django 2.0
I have a Model within my notes application
notes/models.py
class ColorLabels(models.Model):
title = models.CharField(max_lenght=50)
In the sidebar navigation which will be displayed on all pages, I want to show the list of color labels and it will show on all pages.
How can I show dynamic data in all views or say on all pages?

Use a custom template context processor.
This will add the context (data) you need into the templates rendered by all views.
First create the context processor (notes/context_processors.py):
from .models import ColorLabel
def color_labels(request):
return {'color_labels': ColorLabel.objects.all()}
Then add it to the context_processors option of your template renderer in settings.py:
TEMPLATES = [{
'BACKEND': '...',
'OPTIONS': {
'context_processors': [
'notes.context_processors.color_labels',
...
],
},
}]
Finally, you will be able to use it in your templates:
templates/base.html
<nav>
{% for color_label in color_labels %}
{{ color_label.title }}
{% endfor %}
</nav>

Related

Django extend tab into tabular.html existing file

How do I extend/edit the "admin/edit_inline/tabular.html"?
I have this into my settings.py:
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [os.path.join(BASE_DIR, "Metamanager/templates")],
.....
}
My admin.TabularInLineinside the admin.py:
class FileInline(admin.TabularInline):
model = UploadFile
template = os.path.join(BASE_DIR, "Metamanager/templates/tabular.html")
and into my custom template:
{% load i18n admin_urls static admin_modify %}
{% block table_content %}
<td class="original"><p>holaaaaaaaaaaaaa</p></td>
{%endblock%}
not showing the td into the body as I don't know what need to extend into the custom html exactly from tabular.html.
I want to make the link redirect to a view I have don for direct downloading
I need to extend the tabular.html auto created by Django bear in mind I don't have Forms at all, the screenshoot is a Django FileField rendered from models.py

How to display Model in each HTML template?

But create a request in each functions inside views.py I do not want.
Is it possible to output the model in each template using only one request?
I tried to use templateetags but
that so
#register.simple_tag(takes_context=True)
def header_categories(context):
return Categorie.objects.all().order_by('id')
what is like that
#register.simple_tag(takes_context=True)
def header_categories(context):
categories = Categorie.objects.all().order_by('id')
args = {}
for cat in categories:
args[cat.text] = {
'id':cat.id,
}
if cat.parent:
args[cat.text]['parent_id'] = cat.parent.id
args[cat.text]['parent_text'] = cat.parent.text
return args
Nothing works correctly
{% for cat in header_categories %}
cat.text
{% endfor %}
I tried through js
var arr = {%header_categories%}
but django changes everything
{'dresses': {'id': 19},
Before going deeper into your question, I think you should have
{% for cat in header_categories %}
{{ cat.text }}
{% endfor %}
You need to make a custom context processor (See Using RequestContext [Django docs]). What this would do is add a variable to the context for each template. Quoting the documentation:
The context_processors option is a list of callables – called
context processors – that take a request object as their argument and return a dictionary of items to be merged into the context.
In some suitable app of yours make a file named context_processors.py and add this code in it:
def header_categories(request):
return {'header_categories': Categorie.objects.all().order_by('id')}
Now in your settings in the TEMPLATES settings add this context processor to the list context_processors, so it should look like:
[
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'your_app.context_processors.header_categories',
]
Now in your templates you can simply write:
{% for cat in header_categories %}
{{ cat.text }}
{% endfor %}

Django, viewing models from different app

I am super new to python programming and django and i got the basics out of the way. I created a project with two apps, home and video. In my video models.py i have the following data:
class Video(models.Model):
name = models.CharField(max_length=200)
description = models.TextField(blank=True, null=True)
I want to do something with this in my home app in the views.py, such as display the data in an html page and currently it is set up as followed:
from video.models import Video
def display_video(request):
video_list = Video.objects.all()
context = {'video_list': video_list}
return render(request, 'home/home.html', context)
in my home.html
{% if video_list %}
{% for video in video_list %}
<p>{{ video.name }}</p>
<p>{{ video.description }}</p>
{% endfor %}
{% else %}
<p>no videos to display</p>
{% endif %}
my home.html always returns "no videos to display"
But when i query Video.objects.all() in my video app it finds 2 objects. any help is appreciated.
I decided to delete the project and started over brand new but this time I used class views instead of function views. I'm not exactly sure why it didn't run but using class views it worked like a charm. So the equivalent in class views as simple as possible is.
from video.models import Video
class IndexView(generic.ListView):
template_name = 'home/index.html'
context_object_name = 'top_three'
def get_queryset(self):
return Video.objects.all()[:3]
In settings, check the following is there.
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
It worked for me without using class. I just did what we normally do.
from django.shortcuts import render
from AllBlogs.models import Post # getting this post form AllBlogs app
# Create your views here.
def home (request):
# sort posts according to date in descending order
# only a single query is generated and then hit the database that's how this will not affect the performance of database
latest_blogs = Post.objects.all().order_by("-date")[:3]
return render(request,'Home/home.html',{'blog':latest_blogs})
And this is my template
<!--separated it from the home.html because we can use it in AllBlogs.html
and it save our work and time by just including without copying the same data several times-->
{% load static %}
<li>
<!--add field name which we used in models-->
<article class="blog">
<a href="{% url 'blogDetails_page' blog.slug %}"> <!--Different slug for different blog as slug will create a different url-->
<!--dtl filter to add back or url dynamic url creation-->
<image src="{% static 'images/'|add:blog.image_name %}" alt="{{blog.title}}">
<div class="blog__content">
<h3>{{blog.title}}</h3>
<p>{{blog.excerpt}}</P>
</div>
</a>
</article>
</li>
And this is the Post model
# having post data
class Post(models.Model):
title = models.CharField(max_length=150)
date = models.DateField(auto_now=True) # put the date in the field at which time we are saving the data
image_name = models.CharField(max_length=50) # later on we upload files right now we get images from static folder
excerpt = models.CharField(max_length=200)
content = models.TextField(validators=[MinLengthValidator(10)]) # TextFields same like CharField
slug = models.SlugField(unique=True, db_index=True) # set it as unique because we are going to use it as a primary key
author = models.ForeignKey(Author,on_delete=models.SET_NULL,related_name='posts',null=True) # one to many relation
tags = models.ManyToManyField(Tag) # ManyToManyRelation with tag
# represent post entry by it post title
def __str__(self):
return self.title

Passing currently logged user to submit_line.html in Django

I have been trying to get the currently logged user object in submit_line.html to control which buttons it displays. However I have realized that the user object is not passed to the context for submit_row. What would be the best way to pass a the currently logged user object to submit_row. Should I create a new template tag?
Nicola
You can get the current User by accessing the request object:
{{ request.user }}
Just make sure 'django.core.context_processors.request' is included in context_processors setting in settings.py:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
...
],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
...
'django.core.context_processors.request', # this entry is important
],
},
},]
Yes you can also use {{ request.user }} in your template to get login user. And also you can use template tag to get login user for that
first create .py file let's consider 'templatetags.py' and write this view there
#register.assignment_tag(takes_context=True)
def user_tag(context):
request = context['request']
return request.user
Now load this templatetags.py file in your html file i.e.'submit_line.html'
{% load templatetags %}
{% user_tag as user %}
{% if user %}
{{ user }}
{% endif %}
Hope this will help you.

Add "active" navigation class to navbar in Django's class-based views

In a Django app, a lot of class-based views are called directly from the urls.py like so
url(r'^manage/thing/$',
ListView.as_view(model=Thing,
queryset=Thing.objects.filter(parent=None)),
name='mg_thing_list'),
and most CBVs are not subclassed, so views.py is almost empty. I want to highlight the active section in the navbar based on the URL. For example, pages at /manage/thing/... should have class="active" next to the "thing" item in the navbar HTML. What's the DRYest way of doing this?
I want to avoid subclassing the CBVs just to add the request to the template context (which the standard templatetag solution seems to require). Currently we do it in a dumb way: add a {% block %} for every navbar item tag and set the relevant block to class="active" in each and every template. Seems a waste.
First of all, it's not recommended to hold logic in urls.py, also there are 2 ways to go about your issue here
First a template context processor: (in myapp/context_processors.py)
def mytag(request):
context = {'class': 'active'}
return context
Then
<div class='{{ class }}'>
Finally add the template context processor to TEMPLATE_CONTEXT_PROCESSORS in settings.py or in Django 1.8
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': ['components/templates'],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'myapp.context_processors.mytag',
],
},
},
Also, just as a very common opinion on views, you should keep view logic
in views, that way if you needed to build some mixins you could. Keep urls small.
You can use this snippet to add active class to your html code. It does a reverse resolve based on the url name parameter.
In your_app/templatetags/base_utils.py
from django import template
from django.core import urlresolvers
register = template.Library()
#register.simple_tag(takes_context=True)
def current(context, url_name, return_value=' active', **kwargs):
matches = current_url_equals(context, url_name, **kwargs)
return return_value if matches else ''
def current_url_equals(context, url_name, **kwargs):
resolved = False
try:
resolved = urlresolvers.resolve(context.get('request').path)
except:
pass
matches = resolved and resolved.url_name == url_name
if matches and kwargs:
for key in kwargs:
kwarg = kwargs.get(key)
resolved_kwarg = resolved.kwargs.get(key)
if kwarg:
# for the comparison of same type url arg d+ w+
kwarg = unicode(kwarg)
if not resolved_kwarg or kwarg != resolved_kwarg:
return False
return matches
In your_template.html
{% load base_utils %}
<li class="{% current 'your_url_name' param1=param1 param_N=param_N %}"> This is NavBar Button </li>
I have had the question if I understand you correctly, and I solved it by using jQuery like this:
function mainNavListAddClass() {
var theA = $("a[href=" + "'" + getCurrentUrlPath() + "'" + "]");
if (theA.length) {
theA.first().addClass("active");
}
}
function getCurrentUrlPath() {
return location.pathname;
}