I have a model team with attribute name:
class Team(models.Model):
name = models.CharField(max_length=50, null=True, blank=True)
I want to put the team name in the header of the website, as in my template language would be something like:
{% if team.name %}
<h1>{{ team.name }}</h1>
{% endif %}
However the name only displays if I'm on a view that makes a query on the team model. So I guess I need to have that query available across all views/templates. What is the best way of going about this?
Variables you want to set for every template call (well you do not have to use them per se, but typically it pays off when you use these in nearly every template), can be set with context processors.
Context processors are functions that take as input a request parameter, and return a dictionary that maps variable names (so strings) to the content that the parameter should carry, like:
# myapp/context_processors.py
def first_team(request):
return { 'first_team': Team.objects.first() }
We can store these under an app (it does not matter which one, but typically the one that is the closests semantically to what the context processor is doing).
Next we can register our context processor in settings.py. We can alter the TEMPLATES settings, and register the context processor:
# settings.py
TEMPLATES = [
{
# ...
'OPTIONS': {
'context_processors': [
# ...
'myapp.context_processors.first_team',
# ...
],
},
# ...
},
]
In fact it is quite likely that you already have some context processors without ever noticing.
Next you can use {{ first_team }} (and derived products) in every template that you render (without overriding the settings when rendering). Note that you have to be careful about giving variables a name in context processors, since these can override existing ones.
Related
Using Django I want to implement some middleware that will calculate some context that is to be used by the view itself.
For example, I have a middleware that looks at the request, and adds the user's permissions to the request, or some user configuration. The view looks at these permissions and decides how to handle the request using it.
This saves the need for multiple views (and multiple parts within the view) to query for this information.
I'm wondering what is the correct way to do that. One option is to just add request.user_permissions=... directly on the request. But is there some documented and expected way to do that?
There's no real documented way to do that, but Middleware is the correct place to do it and just adding properties to the request object is also the correct way.
You can confirm this, because Django is already doing it:
LocaleMiddelware
AuthenticationMiddleware
RemoteUserMiddleware
CurrentSiteMiddleware
SessionMiddleware
So just pick whatever is the most convenient data structure for your use case and tack that on to the request object.
This is not a perfect answer but at my experience I use this code. Every permission is saved in a boolean value which is true or false. You can access it in a html template like.
{% if request.user.is_admin %}
"Your code here"
{% else %}
"Your code here"
{% endif %}
and to send extra context you should create and pass an dicionary and pass it as as an argument to the render method from the view.
For eg:
def view(request, slug):
context = {'administrator':True}
blog_post = get_object_or_404(BlogPost, slug=slug)
context['blog_post'] = blog_post
return render(request, 'blog/detail_blog.html', context)
and access it like
{% if context.administrator %}
"Your code here"
{% else %}
"Your code here"
{% endif %}
I believe, since your middleware will calculate context, it should be implemented as context processor.
https://docs.djangoproject.com/en/3.1/ref/templates/api/#using-requestcontext
https://docs.djangoproject.com/en/3.1/ref/templates/api/#writing-your-own-context-processors
I'm working on a web page. There will be contact in the footer like email or telephone. This footer should be everywhere so it is in the base.html which is being extended by each template/html.
I've created a table called ContactAdmin, to provide simple and straightforward interface for admin to change his contact info. And here is the problem.
The base.html has no view (it is just for extending) so I don't know how to put there variable - email, telephone from table ContactAdmin. I thought about putting it into every view which is a huge overkill in my opinion.
So how to make Django to read this variables from database and put them into base.html?
The ContactAdmin table should have just one row
You dont need to edit all views. Exactly for this scenario, django has template context processors. The advantage here is, since the base template is still part of the templating language, and it has access to the Context, you just need to set these variables in your custom context processor, and everything should work as is.
Some examples on how to write your custom context processors:
StackOverflow Example
Django example
You can use context processors for this purpose. For instance:
yourapp/context_processors.py
def contact(request):
from yourapp.models import ContactAdmin
contacts = ContactAdmin.objects.all()
return {
'contacts': contact, # Add 'contacts' to the context
}
yourproject/settings.py
TEMPLATES = [
{
...
'OPTIONS': {
'context_processors': [
...
'yourapp.context_processors.contact',
]
}
}
]
I guess these contact settings are not going to change very often. So you may be interested in caching the result of the query as well.
I need a certain context variable in my base.html. This is to contain a set of usernames, e.g. [name1, name2, name3, name4,]. If a logged in user's username is part of this list, I give said user certain preferential treatment and show something in the navbar.
To achieve this, I wrote a template tag:
from django import template
from django.db import models
from django.contrib.auth.models import User
register = template.Library()
VIPS = [name1, name2, name3, name4,]
#register.simple_tag
def verified(user):
return VIPS
register.simple_tag(verified)
And then in base.html, I added {% load verified %} at the top, and then:
{% if user.username in verified %}
<!-- do something -->
{% endif %}
This isn't working. What am I doing wrong? I suspect I've written my template tag incorrectly, but I've tried several, more complex approaches (in vain), at least this simpler one made logical sense to me.
My project's a legacy Django 1.5 project with Python 2.7.
You don't need the register.simple_tag(verified) line, as the #register decorator is already doing that.
However, you might consider a different approach to avoid additional processing in the template, assuming your user is coming from request.user...
#regsiter.assignment_tag(takes_context=True)
def check_user_is_verified(context):
user = context['request'].user
return user and user in vips
Then in your template:
{% check_user_is_verified as is_verified %}
{% if is_verified %}
{# whatever #}
{% endif %}
By leveraging an assignment tag, you can check if the user is verified once, and leverage the context variable you assign instead of having to perform the same list processing each time.
Another alternative is to use a cached property on a custom User object, or a "Profile" model that is linked to your User model via a OneToOneField.
from django.utils.functional import cached_property
class Profile(models.Model):
user = models.OneToOneField(User)
#cached_property
def is_verified(self):
# get the list of vips here
return self.user in vips
If your list of vips changes, just clear the cache key, which you could do via a signal or a Celery task, etc:
del profile_instance.is_verified
Now you have a very efficient property you can check anywhere in your code. My preference tends to be fat models, skinny views and dumb templates.
i'm looking for a way to extend a django template/view.
my first implementation consists of two models (clients/models.py):
class Client(models.Model):
...
class Address(models.Model):
client = models.ForeignKey(Client)
...
and its fairly simple template (clients/detail.html) :
{{client.name}}
Address: {{client.address.street}}, {{client.address.zipcode}} {{client.address.city}}
as my application grows, a new app was born: 'invoices'.
it is again very simple (invoices/models.py):
class Invoice(models.Model):
client = models.ForeignKey(clients.models.Client)
...
now my clients details-view needs to display invoices, so i create and override clients/detail.html in my 'invoices' app.
good for now.
later on i created a third app 'quotes'.
again my clients details-view needs to display quotes.
if i create clients/detail.html in my 'clients' i will loose the ability to display invoices.
because the 'invoices' and 'quotes' app are indipendent.
my first idea was to create something like a SubView-class
which 'invoices' and 'quotes' can extend and then register their implementation somewhere.
a template should look like this:
{{client.name}}
Address: {{client.address.street}}, {{client.address.zipcode}} {{client.address.city}}
{% for view in views %}
<h1>{{view.title}}</h1>
{{view.get_html}}
{% endfor %}
is this a good way to go and should i use a admin.site-like implementation for registering my sub-views?
In Django one url in urls.py should ideally use one view, just to keep things simple.
I would therefore adopt the approach of putting all the required context in your one view for this screen (I think you already have this via foreign keys in your model). Then, rather than doing what you call "SubView-class" I would go for the Django template include tag.
Example:
{% for invoice in client.invoices %}
{% include "invoice-detail.html" with invoice=invoice %}
{% endfor %}
This renders each invoice's detail for all the invoices of the client. Notice how this is in line with the DRY principle.
This is using Google App Engine. I am not sure if this is applicable to just normal Django development or if Google App Engine will play a part. If it does, would you let me know so I can update the description of this problem.
class MessageModel(db.Model):
to_user_id = db.IntegerProperty()
to_user = db.StringProperty(multiline=False)
message = db.StringProperty(multiline=False)
date_created = db.DateTimeProperty(auto_now_add=True)
Now when I do a query a get a list of "MessageModel" and send it to the template.html to bind against, I would like to include a few more properties such as the "since_date_created" to output how long ago since the last output, potentially play around with the message property and add other parameters that will help with the layout such as "highlight" , "background-color" etc...
The only way I thought of is to loop through the initial Query Object and create a new list where I would add the property values and then append it back to a list.
for msg in messagesSQL:
msg.lalaland = "test"
msg.since_created_time = 321932
msglist.append(msg)
Then instead of passing the template.html messagesSQL, I will now pass it msglist.
You should still be able to send it messagesSQL to the template after you've added elements to it via the for loop. Python allows that sort of thing.
Something else that might make sense in some cases would be to give your MessageModel methods. For instance, if you have a
def since_date_created(self):
'''Compute the time since creation time based on self.date_created.'''
Then (assuming you have "messagesSQL" in the template), you can use the function as
{% for msg in messagesSQL %}
{{ msg.since_date_created }}
{% endfor %}
Basically, you can call any method in the model as long as you it needs no arguments passed to it.
You can obtain that by defining methods in the model
like
class MessageModel(db.Model):
# Definition
def since_date_created(self):
# ...
Now in the template, you can use it like
Time since created {{ message.since_date_created }}