Where shall I put 'initialization code' in a Django application? - python

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)?

Related

Sailsjs route and template rendering

This question is directed to anyone with both flask (python) and sailsjs knowledge. I am very new to the concept of web frameworks and such. I started using flask but now I must use Sailsjs. In flask, I can define a route as:
#app.route('/company/<org_name>')
def myfunction(org_name):
...use org_name to filter my database and get data for that company...
return render_template('companies.html', org_name=org_name, mydata=mydata)
Where I can use myfunction() to render a template in which I can pass the parameters org_name and mydata.
In sails, I am confused as to how to define my route with a given parameter. I understand:
'/': {
view: 'companies'
}
but I am not sure how to make the route dynamic in order to accept any variable org_name.
Another problem is that in python, mydata is a query from a MySQL database. I have the same data base connected to Sailsjs with the model completely set up but I am sure this model is useless. The site that I am creating will not be producing any new data (i.e. I will neither be updating nor saving new data to the database).
My Question is thus: with
'/company/:org_name': {
view: 'companies'
}
where should I create the function that filters the database? how should I be sure that sails will pass that org_name parameter into the function and how should I pass the data as a parameter into an html template?
Thanks a ton.
There are 2 options here but it helps to explain a bit about each in order for you to pick the best course of action.
Firstly, routes...You can indeed as you have shown render a view from a route directly, but you can also do a few other things. Below are 2 snippets from the sails.js website docs:
module.exports.routes = {
'get /signup': { view: 'conversion/signup' },
'post /signup': 'AuthController.processSignup',
'get /login': { view: 'portal/login' },
'post /login': 'AuthController.processLogin',
'/logout': 'AuthController.logout',
'get /me': 'UserController.profile'
}
'get /privacy': {
view: 'users/privacy',
locals: {
layout: 'users'
}
},
Snippet 1 shows how you can render a view directly as you have shown but also how you can point to a controller in order to do some more complex logic.
The login within your controller could mean that for the /me "GET" route you can execute a database query within the "profile" method to accept a get parameter, find a user and then display a view with the users data within. An example of that would be:
Profile: function (req,res){
User.find({name: req.param('name')}.exec(function founduser(err,result){
return view('profile',{userdata: result});
});
}
In the second snipped from the sails docs you can see "locals" being mentioned. Here in the GET privacy route we see that the view is being told whether to use the layout template or not. However, with that being said there is nothing stopping you pushing more into the locals such as users name etc.
In my opinion and what I feel is best practice, I would leave your routes.js to be quite thin and logicless, put the database queries/logic/redirections in to your controller.
For your specific example:
My routes.js file may look like this
// config/routes.js
module.exports.routes = {
'get /companies': 'CompanyController.index',
'get /companies/:orgname': 'CompanyController.company'
}
This allows the first route to potentially show a list of companies by going to /companies and my second route may fire when a get request is made based on clicking a company name e.g. /companies/Siemens
My CompanyController.js for these may look like this:
module.exports = {
index: function (req, res) {
return res.view('companieslist');
},
company: function (req, res) {
var companyName = req.param('orgname'); //Get the company name supplied
//My company model which could be in api/models as Company.js is used to find the company
Company.find({name: companyName}).limit(1).exec(function companyresult(err,result){
//Error catch
if(err){return res.negotiate(err)};
//The result of our query is pushed into the view as a local
return res.view('company',{companydata: result}); //Within the .find callback to ensure we keep async
});
}
};
In my view I can access the data retrieved under "companydata" e.g. for EJS:
<%=companydata[0].name%>
If you need any further help/clarifications let me know. I do recommend taking a look at the sails.js documentation but if you really want to get your head around things I recommend sails.js in Action which is an ebook from mannings. A couple of days of reading really got me up to speed!

How to put variable from database into base.html template?

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.

Only run context preprocessor for views from my app

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 {}

python django settings perform sql statement

I want to define a constant variable in my settings.py file, that will be available in the entire app.
i.e. if I do in my settings.py, for example:
VAR = [1,2,3]
then in my view I can access it like:
var = settings.VAR
But, I want that VAR will be fetched from a database.
means, when my app starts, SQL is performed and loads the answer to VAR.
So I've attempted to create a function in views.py that does that:
in views.py:
def loadVAR():
... # perform sql
return VAR
and in settings.py:
import myapp.views
VAR = myapp.views.loadVAR()
But it does not work and I get an "500 Internal server error"
I also haven't managed to perform the SQL directly in settings as well.
How can I achieve this ?
You can achieve this using middleware before touching the view,
class ModelMiddleware(object):
"""
Model data
"""
def process_request(self, request):
# Fetch your data
# Append var data to request
request.META['VAR'] = [1, 2, 3]
return None
You can get the VAR in view using request,
def veiw_data(request, ):
print request.META['VAR']
Here is How to set django middleware in settings file
Update:
If you want to call the sql only first time project loads use this way,
I imagined my project structure this way,
mysite/
mysite/
__init__.py --> Add the logic in this file,
urls.py
settings.py
test.py
manage.py
__init__.py
from catalog.models import Product
import settings
settings.VAR = Product.objects.all()
Done. You can access the VAR in your project. Hope this may be helpful
settings.py is not meant to be used that way, if you want to store some settings in a database, consider using some external package which was designed for that, here is the list of some of them.

Is possible to save render_to_response template from django to server?

I created web application in Python, Django framework. Web application gets data from MongoDB database, it gets about 10000 documents from MongoDB database and works very slow. Now looking for ways to speed up my web app. So, is it possible to store result from method render_to_response as HTML temporarily on server? It looks like this:
I have a HTML form; when the user types data in the form and clicks on submit button, web app executes a view that gets data from the Mongo database, and sends that data via variable mongo_data to home.html:
return render_to_response('home.html', {'mongo_data': mongo_data, 'request': request},
context_instance=RequestContext(request))
home.html show data that are stored in variable mongo_data. In the web application, I have a lot of identical queries, for identical queries I get identical result for home.html. So I want to store home.html to folder for example temp on server, and when user types data in the HTML form and clicks the submit button, first to check is if home.html for his data is in temp folder; if it is, then load that home.html, if not then go to view which will generate new home.html with specific mongo_data.
If this is possible , it will speed up my web app a lot ..
The Django caching framework was made exactly for this purpose; see https://docs.djangoproject.com/en/dev/topics/cache/.
In your case, you either cache the entire view for a period of time:
#cache_page(60 * 15)
def my_mongo_view(request):
return render_to_response('home.html', ...)
(From https://docs.djangoproject.com/en/dev/topics/cache/#the-per-view-cache)
or you use the Low-level Cache API (https://docs.djangoproject.com/en/dev/topics/cache/#the-low-level-cache-api):
from django.core.cache import cache
def my_mongo_view(request):
ret = cache.get('home-rendered')
if ret is None:
ret = render_to_response('home.html', ...)
cache.set('home-rendered', ret)
return ret
You'll find more options for caching (e.g. inside your templates) if you just read the doc.
P.S. you can also parametrize your cache by a variable or user ID or something else.

Categories

Resources