In my django app ("pm"), I have a template context processor that adds a number of variables to every view:
def menu_items(request):
return {
'projects': Project.objects.all().order_by('name'),
'people': People.objects.filter(Q(group="MAAD") | Q(group="OAR")).order_by('name')
}
The problem is, my app is just one of many running on our django project/instance/server/whatever. Since this is added to the TEMPLTATE_CONTEXT_PROCESSOR constant, it will be executed every time any app's view runs. I want to ensure that this only runs when the views from my app are called, so as to avoid adding overhead to views from other apps. How can I verify that the view being called is from my app? In case it helps, I do have namespacing set up for my app:
url(r'^pm/', include('pm.urls', namespace="pm")),
...but I couldn't figure out a way to check the namespace of a view on the fly. Any suggestions would be most appreciated!
As of 1.5, a ResolverMatch object is stored on request.resolver_match, which contains a list of namespaces of the current url:
def menu_items(request):
if 'pm' in request.resolver_match.namespaces:
return {
'projects': Project.objects.all().order_by('name'),
'people': People.objects.filter(Q(group="MAAD") | Q(group="OAR")).order_by('name')
}
return {}
Related
I build web application with Django REST Framework. There is one simple view, which return reference Information with db fields.
resources.py:
RESOURCES = {
'genres': GenreSerializer(Genre.objects.all(), many=True).data,
'authors': AuthorSerializer(Author.objects.all(), many=True).data,
......
}
class ResourceApiView(views.APIView):
def get(self, request):
params = request.query_params
response_dict = {}
if params:
# Return RESOURSES based on query params
for i in params:
q = RESOURCES.get(i)
if q:
response_dict[i] = q
else:
# Return all RESOURSES
response_dict = RESOURCES
return Response(response_dict,
status=status.HTTP_200_OK
)
It works fine, but when I add new object to one the resources querysets. Nothing happens, it show old queries.
I tried printed RESOURSES in my module, it printed once and other get requests don't trigger it.
Then I move RESOURSES directly in class ResourceApiView and it's behavior same like when RESOURSES where in module.
class ResourceApiView(views.APIView):
RESOURCES = {
'genres': GenreSerializer(Genre.objects.all(), many=True).data,
'authors': AuthorSerializer(Author.objects.all(), many=True).data,
......
}
def get(self, request):
...
It work fine only when I put RESOURSES in get method.
class ResourceApiView(views.APIView):
def get(self, request):
RESOURCES = {
'genres': GenreSerializer(Genre.objects.all(), many=True).data,
'authors': AuthorSerializer(Author.objects.all(), many=True).data,
......
}
But why is it happening? Why I can't evaluate queries from class attributes for each method call?
this is more related to python than to django. Let's say you hava file lib.py
def say_hello():
print "hello"
GREETINGS = {
"hello": say_hello()
}
now go to another python file (or the shell) and just import your lib.py, you'll print "hello" to the console because when you import the file It starts resolving the code inside so it's creating the GREETINGS variable (RESOURCES in your case) and calling the say_hello() method, for you it's executing the query. However python is smart enough that if you import the file again he'll remember that you just imported it before so it wont load the module again, cause it already has the module reference saved.
Your query is beeing executed once when the view was first loaded, and reimporting the view wont make the reference change
The same for placing RESOURCES as a class attribute. The code was executed when the class was imported (again you can test it by creating a class on the lib.py example)
hope this clarifies :) but maybe the docs explains it better https://docs.python.org/2/tutorial/modules.html
Note:
I think that the .data on the serializer is actually executing the query. Without it your query and the serializer would just be stored as reference, because the ORM is lazy. Change your RESOURCES to improve the performance of your endpoint because right now if you request one single resource (e.g. 'authors) its still executing ALL the queries ('authors', 'genres', etc)
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.
<p>Hello, my name is {{ name }} ! </p>
Where/how do I set the variable: name = 'mike'? I've tried putting this in the settings.py and models.py file and it does not work.
Any info of proper code to put in a .py file would be great! I've searched through the docs page but didn't see how to set a variable for retrieval.
You need to set your variable value in the view function which normally put in view.py
e.g.
def hello(request):
return render(request, "hello.html", {"name": "mike"})
And you may would like to check https://docs.djangoproject.com/en/dev/topics/http/shortcuts/#render to find more about how to render templates with passed variables.
You need also learn more about how does Django's URL mapping works https://docs.djangoproject.com/en/dev/ref/urls/
Use context processors in django. Django handles this dilemma of making some information available to
all pages with something called context processors.
Some Code is like this,
Create a new file called context_processors.py inside your utils app directory, and add the
following code to it:
from project import settings
def context_data(request):
return {
'name': settings.name,
'request': request
}
I want some code in my Django app to be executed only once when server is started, not per request.
Specifically, I want to load some database tables into memory. These tables contain some 'metadata' that doesn't change per request. Like this:
ProductTypesData = None;
def loadProductTypesData():
productTypes = ProductType.objects.all();
for ptype in productTypes:
ptype_data = {
"id":ptype.id,
"name": ptype.name,
"description":ptype.desc
};
ProductTypesData.append(ptype_data);
loadProductTypesData();
Where should I put this code?
Other Q/A about django initialization suggest to put it in urls.py. But importing the models in urls.py doesn't seem logical to me.
Can I just put the code in models.py? Does it get executed only once (if it is acceptable to be executed not on django start)?
tl:dr
How would a hosted django app correctly transform resource paths to match any hosted location (/ or /test or /testtest)?
Full Description
Let me try to explain what I am trying to do.
I am trying to write a somewhat re-usable django app which I intend to use from within multiple projects. This app is called systemstatus.
The systemstatus app provides a page under '$^' which provides a simple interface to query the system status.
This page makes an ajax query back to the systemstatus app to determine the actual system status and report it on the UI.
The systemstatus app provides a location '^service/$' which points to the ajax call handler.
This page has to somehow figure out the correct URI for the ajax handler depending on where this app is hosted (e.g. under / or /status or /blahblah).
I am wondering what an ideal way of doing this would be. I would say that this applies to other resources bundled inside the app too (stylesheets, images).
Right now I am using request.path to determine what the target path should be. This path is then passed down as a parameter to the template. But this approach will soon become too cumbersome to handle.
def system_status (request):
queryPath = request.path + "service/"
return render_to_response ('systemstatus.html', {'queryPath': queryPath})
My page template looks like this:
function do_ajax () {
$.getJSON ('{{ queryPath }}', function (data) {
$("#status").html (data.status);
});
}
Thanks!
You shouldn't hardcode your urls like that, but use reverse instead!
Django also has a built-in template tag to reverse urls. So you could do something like
function do_ajax () {
$.getJSON ('{% url path.to.my_ajax_view %}', function (data) {
$("#status").html (data.status);
});
}
directly in your template!
You can also send the ajax request directly to your current page's url and check if it is an ajax request or not:
def my_view(request):
if request.is_ajax():
# generate response for your ajax script
else:
# generate the response for normal request
# (render template of your page)