D:\Program Files (x86)\python273;D:\Program Files (x86)\python273\Lib\lib-tk;D:\Program Files (x86)\python273\DLLs;D:\Program Files (x86)\python273\Lib;
Monday, December 31, 2012
google chart tools
in the Google Chart Tools documentation:
Options: hAxis.showTextEvery
in the code
new google.visualization.LineChart(document.getElementById('block_line_visualization')).
draw(data, { title: "y-axis: Quantity | x-axis: Time-Frame",
width: 700, height: 700,
vAxis: {maxValue: 6},
hAxis: {showTextEvery:1}
}
);
Sunday, December 30, 2012
Windows 8 Use touchpad while “typing
http://superuser.com/questions/504571/use-touchpad-while-typing
synpnatics:
in the mouse setting, set the palm check to minimum
synpnatics:
in the mouse setting, set the palm check to minimum
Saturday, December 29, 2012
Aggregate Function in Djano Model
>>> from terminal_app.models import CntrOffload
>>> from django.db.models import Min
>>> CntrOffload.objects.aggregate(Min('exec_datetime'))
{'exec_datetime__min': datetime.datetime(2012, 12, 22, 0, 16, 28)}
>>> CntrOffload.objects.filter(vv_c='4588').aggregate(Min('exec_datetime'))
{'exec_datetime__min': datetime.datetime(2012, 12, 26, 3, 30, 32)}
>>>
Bootstrap grid with {%ifchanged xx%}
<div>
<div class="row-fluid"></div> #otherwise not in position
{% for block in blocks %}
{% if forloop.counter|divisibleby:"6" %}
<div class="row">
{% endif %}
{% ifchanged block.code %}
<div class="span2">
{{ block.code }}
</div>
{% endifchanged %}
{% if forloop.counter|divisibleby:"6" %}
</div>
{% endif %}
{% endfor %}
</div>
Thursday, December 27, 2012
datepicker Enable Specific Dates
http://codeasp.net/blogs/raghav_khunger/microsoft-net/1087/jquery-datepicker-enable-specific-dates
dict['dateObjs'] = AvailableDate.objects.all()
<script type="text/javascript">
$(function () {
//'12-22-2012'
var daysToEnable = [
{% for dateObj in dateObjs %}
'{{ dateObj.date|date:"m-d-Y"}}'{% if not forloop.last %},{% endif %}
{% endfor %}
];
$('#datepicker').datepicker({
beforeShowDay: enableSpecificDates,
dateFormat: 'M. dd, yy'
});
function enableSpecificDates(date) {
var month = date.getMonth();
var day = date.getDate();
var year = date.getFullYear();
for (i = 0; i < daysToEnable.length; i++) {
if ($.inArray((month + 1) + '-' + day + '-' + year, daysToEnable) != -1) {
return [true];
}
}
return [false];
}
});
dict['dateObjs'] = AvailableDate.objects.all()
<script type="text/javascript">
$(function () {
//'12-22-2012'
var daysToEnable = [
{% for dateObj in dateObjs %}
'{{ dateObj.date|date:"m-d-Y"}}'{% if not forloop.last %},{% endif %}
{% endfor %}
];
$('#datepicker').datepicker({
beforeShowDay: enableSpecificDates,
dateFormat: 'M. dd, yy'
});
function enableSpecificDates(date) {
var month = date.getMonth();
var day = date.getDate();
var year = date.getFullYear();
for (i = 0; i < daysToEnable.length; i++) {
if ($.inArray((month + 1) + '-' + day + '-' + year, daysToEnable) != -1) {
return [true];
}
}
return [false];
}
});
Popover
<a href="#" class="btn btn-primary btn-small changeButton"
rel="popover" data-placement="bottom"
data-html="true"
data-content="
<form action='/start/' method='post'>{% csrf_token %}
<fieldset>
<legend>Date Selection</legend>
<label>date:
<input type='text' id='datepicker' name='date' placeholder='date of view'>
</label>
<button type='submit' class='btn btn-primary btn-small' value='submit'>Submit</button>
</fieldset>
</form>"
>
Change</a>
ajax
loading page
loading animation
http://jsfiddle.net/VpDUG/1844/
Wednesday, December 26, 2012
Bootstrap Carousel
<div id="myCarousel" class="carousel slide">
<!-- Carousel items -->
<div class="carousel-inner">
<div class="active item">
<img src="http://www.act.com.hk/images/en_leading06_psa.jpg" alt="">
<div class="carousel-caption">
<h4>First Thumbnail label</h4>
<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.</p>
</div>
</div>
<div class="item">
</div>
<div class="item">
</div>
</div>
<!-- Carousel nav -->
<a class="carousel-control left" href="#myCarousel" data-slide="prev">‹</a>
<a class="carousel-control right" href="#myCarousel" data-slide="next">›</a>
</div>
Tuesday, December 25, 2012
Python dictionary and zip
- len(myDict)
- eletment in myDict
- for key in myDict:
- for key in myDict.keys()
- for key, value in myDict.items():
- for value in myDict.values():
- myDict,ckear()
- aDict,update(bDict) - for each key in bDict, updates aDict with that key/value pair
zip() is the built-in function
- zip("abc", [1, 2, 3]) --> [(‘a’,1),(‘b’,2),(‘c’,3)]
- dict(zip("abc", [1, 2, 3]) -->{'a': 1, 'c': 3, 'b': 2}
aString = "\n".join(aList)
aList = aString.split("\n")
OrderedDict
reports = collections.OrderedDict()
the OrderedDict will remember the sequence of key insertion
Chrome Shortcuts on Windows
source: https://support.google.com/chrome/bin/answer.py?hl=en&answer=157179
Tab and window shortcuts
Ctrl+N | Opens a new window. |
Ctrl+T | Opens a new tab. |
Ctrl+Shift+N | Opens a new window in incognito mode. |
Press Ctrl+O, then select file. | Opens a file from your computer in Google Chrome. |
Press Ctrl and click a link. Or click a link with your middle mouse button (or mousewheel). | Opens the link in a new tab in the background . |
Press Ctrl+Shift and click a link. Or pressShift and click a link with your middle mouse button (or mousewheel). | Opens the link in a new tab and switches to the newly opened tab. |
Press Shift and click a link. | Opens the link in a new window. |
Ctrl+Shift+T | Reopens the last tab you've closed. Google Chrome remembers the last 10 tabs you've closed. |
Drag a link to a tab. | Opens the link in the tab. |
Drag a link to a blank area on the tab strip. | Opens the link in a new tab. |
Drag a tab out of the tab strip. | Opens the tab in a new window. |
Drag a tab out of the tab strip and into an existing window. | Opens the tab in the existing window. |
Press Esc while dragging a tab. | Returns the tab to its original position. |
Ctrl+1 through Ctrl+8 | Switches to the tab at the specified position number on the tab strip. |
Ctrl+9 | Switches to the last tab. |
Ctrl+Tab or Ctrl+PgDown | Switches to the next tab. |
Ctrl+Shift+Tab or Ctrl+PgUp | Switches to the previous tab. |
Alt+F4 or Ctrl + Shift + W | Closes the current window. |
Ctrl+W or Ctrl+F4 | Closes the current tab or pop-up. |
Click a tab with your middle mouse button (or mousewheel). | Closes the tab you clicked. |
Right-click, or click and hold either the Back or Forward arrow in the browser toolbar. | Displays your browsing history in the tab. |
Press Backspace, or Alt and the left arrow together. | Goes to the previous page in your browsing history for the tab. |
Press Shift+Backspace, or Alt and the right arrow together. | Goes to the next page in your browsing history for the tab. |
Press Ctrl and click either the Back arrow, Forward arrow, or Go button in the toolbar. Or click either button with your middle mouse button (or mousewheel). | Opens the button destination in a new tab in the background. |
Double-click the blank area on the tab strip. | Maximizes or minimizes the window. |
Alt+Home | Opens your homepage in your current window. |
Google Chrome feature shortcuts
Alt+F or Alt+E or F10 | Opens the Chrome menu , which lets you customize and control settings in Google Chrome. |
Ctrl+Shift+B | Toggles the bookmarks bar on and off. |
Ctrl+H | Opens the History page. |
Ctrl+J | Opens the Downloads page. |
Shift+Esc | Opens the Task Manager. |
Shift+Alt+T | Sets focus on the first tool in the browser toolbar. You can then use the following shortcuts to move around in the toolbar:
|
F6 or Shift+F6 | Switches focus to the next keyboard-accessible pane. Panes include:
|
Ctrl+Shift+J | Opens Developer Tools. |
Ctrl+Shift+Delete | Opens the Clear Browsing Data dialog. |
F1 | Opens the Help Center in a new tab (our favorite). |
Ctrl+Shift+M | Switch between multiple users. |
Address bar shortcuts
Use the following shortcuts in the address bar:Type a search term, then press Enter. | Performs a search using your default search engine. |
Type a search engine keyword, press Space, type a search term, and press Enter. | Performs a search using the search engine associated with the keyword. |
Begin typing a search engine URL, press Tabwhen prompted, type a search term, and press Enter. | Performs a search using the search engine associated with the URL. |
Ctrl+Enter | Adds www. and .com to your input in the address bar and open the resulting URL. |
Type a URL, then press Alt+Enter. | Opens the URL in a new tab. |
Ctrl+L or Alt+D | Highlights the URL. |
Ctrl+K or Ctrl+E | Places a '?' in the address bar. Type a search term after the question mark to perform a search using your default search engine. |
Press Ctrl and the left arrow together. | Moves your cursor to the preceding key term in the address bar |
Press Ctrl and the right arrow together. | Moves your cursor to the next key term in the address bar |
Ctrl+Backspace | Deletes the key term that precedes your cursor in the address bar |
Select an entry in the address bar drop-down menu with your keyboard arrows, then pressShift+Delete. | Deletes the entry from your browsing history, if possible. |
Click an entry in the address bar drop-down menu with your middle mouse button (or mousewheel). | Opens the entry in a new tab in the background. |
Press Page Up or Page Down when the address bar drop-down menu is visible. | Selects the first or last entry in the drop-down menu. |
Webpage shortcuts
Ctrl+P | Prints your current page. |
Ctrl+S | Saves your current page. |
F5 or Ctrl+R | Reloads your current page. |
Esc | Stops the loading of your current page. |
Ctrl+F | Opens the find bar. |
Ctrl+G or F3 | Finds the next match for your input in the find bar. |
Ctrl+Shift+G, Shift+F3, or Shift+Enter | Finds the previous match for your input in the find bar. |
Click the middle mouse button (or mousewheel). | Activates auto-scrolling. As you move your mouse, the page automatically scrolls according to the direction of the mouse. |
Ctrl+F5 or Shift+F5 | Reloads your current page, ignoring cached content. |
Press Alt and click a link. | Downloads the target of the link. |
Ctrl+U | Opens the source of your current page. |
Drag a link to bookmarks bar | Saves the link as a bookmark. |
Ctrl+D | Saves your current webpage as a bookmark. |
Ctrl+Shift+D | Saves all open pages as bookmarks in a new folder. |
F11 | Opens your page in full-screen mode. PressF11 again to exit full-screen. |
Ctrl and +, or press Ctrl and scroll your mousewheel up. | Enlarges everything on the page. |
Ctrl and -, or press Ctrl and scroll your mousewheel down. | Makes everything on the page smaller. |
Ctrl+0 | Returns everything on the page to normal size. |
Space bar | Scrolls down the web page. |
Home | Goes to the top of the page. |
End | Goes to the bottom of the page. |
Press Shift and scroll your mousewheel. | Scrolls horizontally on the page. |
Text shortcuts
Ctrl+C | Copies highlighted content to the clipboard. |
Ctrl+V or Shift+Insert | Pastes content from the clipboard. |
Ctrl+Shift+V | Paste content from the clipboard without formatting. |
Ctrl+X or Shift+Delete | Deletes the highlighted content and copies it to the clipboard. |
Monday, December 24, 2012
access key and element in dictionary in Django Template
{% for key, value in dictionary.items %}
<p>{{ key }} - {{ value }}</p>
{% endfor %}
Subversion
Subversion version control
- Assembla
- My Start
- Free Private SVN Subversion (scroll down, there is a free onw)
- Import the root directory of your folder (PyCharm VCS)
- Username and password (username is Assembla Log in ID rather than Email Address)
- VCS -> Enable Subversion Intergarion
Sunday, December 23, 2012
Chapter 12: Deploying Django
Deploying Django Application to a Production Server
Apache: industrial-strength Web Server
1. settings.py
DEBUG = False
TEMPLATE_DEBUG = False
2. root template directory
404.html
500.html
(not rely on other templates)
unhandled Python exception
http://www.djangobook.com/en/2.0/chapter12.html
Three ways:
override
3. use of Python logic
IF the name of settings changed:
You can fix this by editing manage.py to change settingsto the name of your module
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "quality.settings_XXX")
make sure you have Apache installed with the mod_python module activated.
Make sure to replace mysite.settings with the appropriate DJANGO_SETTINGS_MODULE for your site.
This tells Apache, “Use mod_python for any URL at or under ‘/’, using the Django mod_python handler.” It passes the value of DJANGO_SETTINGS_MODULE so mod_python knows which settings to use.
Note that we’re using the <Location> directive, not the <Directory> directive. The latter is used for pointing at places on your filesystem, whereas <Location> points at places in the URL structure of a Web site. <Directory> would be meaningless here.
Apache likely runs as a different user than your normal login and may have a different path and sys.path. You may need to tell mod_python how to find your project and Django itself.
However, as traffic increases you’ll quickly run into resource contention between the different pieces of software.
As far as Django is concerned, the process of separating out the database server is extremely easy: you’ll simply need to change the DATABASE_HOST setting to the IP or DNS name of your database server. It’s probably a good idea to use the IP if at all possible, as relying on DNS for the connection between your Web server and database server isn’t recommended.
For sites heavy in static content (photos, videos, etc.), moving to a separate media server is doubly important. Three-server setup: 10 million hits a day
Performance Tuning
Of course, selecting memcached does you no good if you don’t actually use it. Chapter 15 is your best friend here: learn how to use Django’s cache framework, and use it everywhere possible. Aggressive, preemptive caching is usually the only thing that will keep a site up under major traffic.
done
done
Apache: industrial-strength Web Server
Preparing Your Codebase for Production
1. settings.py
DEBUG = False
TEMPLATE_DEBUG = False
2. root template directory
404.html
{% extends "base.html" %} {% block title %}Page not found{% endblock %} {% block content %} <h1>Page not found</h1> <p>Sorry, but the requested page could not be found.</p> {% endblock %}
500.html
(not rely on other templates)
unhandled Python exception
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<title>Page unavailable</title>
</head>
<body>
<h1>Page unavailable</h1>
<p>Sorry, but the requested page is unavailable due to a
server hiccup.</p>
<p>Our engineers have been notified, so check back later.</p>
</body>
</html>3. Setting Up Error Alters and Setting Up Broken Link Alerts
Need Email Set upADMINS = ( ('John Lennon', 'jlennon@example.com'), ('Paul McCartney', 'pmacca@example.com'), )
http://www.djangobook.com/en/2.0/chapter12.html
Using Multiple settings.py for Development and Production
Three ways:
- Two independent settings files
- base setting file and inherited setting file
- one single setting.py with Python logic to change the settings based on context
1. Copy as settings.py settings_production.py
2. IMPORT
# settings.py DEBUG = True TEMPLATE_DEBUG = DEBUG DATABASE_ENGINE = 'postgresql_psycopg2' DATABASE_NAME = 'devdb' DATABASE_USER = '' DATABASE_PASSWORD = '' DATABASE_PORT = '' # ... # settings_production.py from settings import * DEBUG = TEMPLATE_DEBUG = False DATABASE_NAME = 'production' DATABASE_USER = 'app' DATABASE_PASSWORD = 'letmein'
override
3. use of Python logic
# settings.py import socket if socket.gethostname() == 'my-laptop': DEBUG = TEMPLATE_DEBUG = True else: DEBUG = TEMPLATE_DEBUG = False # ...
IF the name of settings changed:
You can fix this by editing manage.py to change settingsto the name of your module
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "quality.settings_XXX")
Apache + mod_python
Basic Configuration
make sure you have Apache installed with the mod_python module activated.
LoadModule python_module /usr/lib/apache2/modules/mod_python.soThen, edit your Apache configuration file and add a <Location> directive that ties a specific URL path to a specific Django installation.
<Location "/"> SetHandler python-program PythonHandler django.core.handlers.modpython SetEnv DJANGO_SETTINGS_MODULE mysite.settings PythonDebug Off </Location>
Make sure to replace mysite.settings with the appropriate DJANGO_SETTINGS_MODULE for your site.
This tells Apache, “Use mod_python for any URL at or under ‘/’, using the Django mod_python handler.” It passes the value of DJANGO_SETTINGS_MODULE so mod_python knows which settings to use.
Note that we’re using the <Location> directive, not the <Directory> directive. The latter is used for pointing at places on your filesystem, whereas <Location> points at places in the URL structure of a Web site. <Directory> would be meaningless here.
Apache likely runs as a different user than your normal login and may have a different path and sys.path. You may need to tell mod_python how to find your project and Django itself.
PythonPath "['/path/to/project', '/path/to/django'] + sys.path"
Running Multiple Django Installations on the Same Apache Instance
to be continued
Running a Development Server with mod_python
Serving Django and Media Files from the Same Apache Instance
Alternative:
Using Django with FastCGI
http://www.djangobook.com/en/2.0/chapter12.html
Scaling
Performance Tuning
There’s No Such Thing As Too Much RAM
This shouldn’t be too hard; we’ve developed a site with more than half a million newspaper articles, and it took under 2GB of space.Turn Off Keep-Alive
Use memcached
done
done
Chapter 9 Advanced Template
A context is a name -> value mapping (similar to a Python dictionary) that is passed to a template.
instance of django.template.Context, but Django also comes with a special subclass, django.template.RequestContext, that acts slightly differently. RequestContextadds a bunch of variables to your template context by default – things like the HttpRequest object or information about the currently logged-in user.
Use RequestContext when you don’t want to have to specify the same set of variables in a series of templates.
RequestContext and Context Processors
instance of django.template.Context, but Django also comes with a special subclass, django.template.RequestContext, that acts slightly differently. RequestContextadds a bunch of variables to your template context by default – things like the HttpRequest object or information about the currently logged-in user.
Use RequestContext when you don’t want to have to specify the same set of variables in a series of templates.
Avoid repeating the same values in the context dictionary
Point: a context with many similar elements
DO NOT REPEAT YOURSELF
MOST LOW-LEVEL
context processor: it takes an HttpRequest object and returns a dictionary of variables to use in the template context
c1 = Context({ 'app': 'My app', 'user': request.user, 'ip_address': request.META['REMOTE_ADDR'], 'message': 'I am view 1.' })
c1 = Context({
'app': 'My app',
'user': request.user,
'ip_address': request.META['REMOTE_ADDR'],
'message': 'I am the second view.'
})
from django.template import loader, RequestContext def custom_proc(request): "A context processor that provides 'app', 'user' and 'ip_address'." return { 'app': 'My app', 'user': request.user, 'ip_address': request.META['REMOTE_ADDR'] } def view_1(request): # ... t = loader.get_template('template1.html') c = RequestContext(request, {'message': 'I am view 1.'}, processors=[custom_proc]) return t.render(c) def view_2(request): # ... t = loader.get_template('template2.html') c = RequestContext(request, {'message': 'I am the second view.'}, processors=[custom_proc]) #list return t.render(c)
# naming convention: processorName_proc
processors argument, which is a list or tuple of context processor functions to use.
render_to_reponse() + RequestContext
GLOBAL CONTEXT-LEVEL (Not really understood)
global context processors
This setting is a tuple of callables that use the same interface as our custom_proc function above – functions that take a request object as their argument and return a dictionary of items to be merged into the context.
Auto escape
Django has two ways to load templates:
django.template.loaders.filesystem.load_template_source: This loader loads templates from the filesystem, according to TEMPLATE_DIRS. It is enabled by default.
django.template.loaders.app_directories.load_template_source: This loader loads templates from Django applications on the filesystem. For each application in INSTALLED_APPS, the loader looks for a templates subdirectory. If the directory exists, Django looks for templates there.
This means you can store templates with your individual applications, making it easy to distribute Django applications with default templates. For example, if INSTALLED_APPS contains('myproject.polls', 'myproject.music'), then get_template('foo.html') will look for templates in this order:
/path/to/myproject/polls/templates/foo.html
/path/to/myproject/music/templates/foo.html
Note that the loader performs an optimization when it is first imported: it caches a list of which INSTALLED_APPS packages have a templates subdirectory.
This loader is enabled by default.
django.template.loaders.eggs.load_template_source: This loader is just like app_directories, except it loads templates from Python eggs rather than from the filesystem. This loader is disabled by default; you’ll need to enable it if you’re using eggs to distribute your application. (Python eggs are a way of compressing Python code into a single file.)
Django uses the template loaders in order according to the TEMPLATE_LOADERS setting. It uses each loader until a loader finds a match.
Three steps of creating template library
correspond to the poll_extras.py # your custom defined tag/filter
The {% load %} tag looks at your INSTALLED_APPS setting (new app for template library must be added in setting)and only allows the loading of template libraries within installed Django applications. This is a security feature; it allows you to host Python code for many template libraries on a single computer without enabling access to all of them for every Django installation.
When Django compiles a template, it splits the raw template text into nodes. Each node is an instance of django.template.Node and has a render() method. Thus, a compiled template is simply a list of Node objects. For example, consider this template:
Thus, to define a custom template tag, you specify how the raw template tag is converted into a Node (the compilation function) and what the node’s render() method does.
{% xxx %} parser
User-defined {% current_time %} #actually available: {% now %}
token.contents is a string of the raw contents of the tag. In our example, it’s'current_time "%Y-%m-%d %I:%M %p"'.
parser is the template parser object. We don’t use it in this example. token is the token currently being parsed by the parser.
parser.parse() takes a tuple of names of template tags to parse until. It returns an instance ofdjango.template.NodeList, which is a list of all Node objects that the parser encountered before it encountered any of the tags named in the tuple.
So in the preceding example, nodelist is a list of all nodes between {% comment %} and {% endcomment %}, not counting {% comment %} and {% endcomment %} themselves.
After parser.parse() is called, the parser (not nodeList from parser.parse) hasn’t yet “consumed” the {% endcomment %} tag, so the code needs to explicitly call parser.delete_first_token() to prevent that tag from being processed twice.
take a single argument, and return a string -> shortcut for it
Another common template tag is the type that displays some data by rendering ANOTHER template
result in
1. function
2. Template
3. Register
to be continued...
http://www.djangobook.com/en/2.0/chapter09.html
done
processors argument, which is a list or tuple of context processor functions to use.
def view_2(request): # ... return render_to_response('template2.html', {'message': 'I am the second view.'}, context_instance=RequestContext(request, processors=[custom_proc]))END MOST LOW-LEVEL
GLOBAL CONTEXT-LEVEL (Not really understood)
global context processors
This removes the need to specify processors each time you use RequestContext
For that reason, Django provides support for global context processors. The TEMPLATE_CONTEXT_PROCESSORSsetting (in your settings.py) designates which context processors should always be applied to RequestContext.
For that reason, Django provides support for global context processors. The TEMPLATE_CONTEXT_PROCESSORSsetting (in your settings.py) designates which context processors should always be applied to RequestContext.
TEMPLATE_CONTEXT_PROCESSORS = ( #tuple 'django.core.context_processors.auth', 'django.core.context_processors.debug', 'django.core.context_processors.i18n', 'django.core.context_processors.media', )
django.core.context_processors.auth
- user
- messages
- perms
django.core.context_processors.debug
- debug
- sql_queries
django.core.context_processors.i18n
- LANGUAGES
- LANGUAGE_CODE
Auto escape
(template variable, variable from view functions)
{{ data|default:"3 < 2" }}
...rather than
{{ data|default:"3 < 2" }} <-- Bad! Don't do this.
This doesn’t affect what happens to data coming from the variable itself.
Generally, template authors don’t need to worry about auto-escaping very much. Developers on the Python side (people writing views and custom filters) need to think about the cases in which data shouldn’t be escaped, and mark data appropriately, so things work in the template.Inside Template Loading
Generally, you’ll store templates in files on your filesystem, but you can use custom template loaders to load templates from other sources.Django has two ways to load templates:
- django.template.loader.get_template(template_name)
- django.template.loader.select_template(template_name_list)
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
# 'django.template.loaders.eggs.Loader',
)
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
# 'django.template.loaders.eggs.Loader',
)
TEMPLATE_DIRS = (
os.path.join(os.path.dirname(__file__), 'template').replace('\\','/'),
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
)
os.path.join(os.path.dirname(__file__), 'template').replace('\\','/'),
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
)
django.template.loaders.filesystem.load_template_source: This loader loads templates from the filesystem, according to TEMPLATE_DIRS. It is enabled by default.
django.template.loaders.app_directories.load_template_source: This loader loads templates from Django applications on the filesystem. For each application in INSTALLED_APPS, the loader looks for a templates subdirectory. If the directory exists, Django looks for templates there.
This means you can store templates with your individual applications, making it easy to distribute Django applications with default templates. For example, if INSTALLED_APPS contains('myproject.polls', 'myproject.music'), then get_template('foo.html') will look for templates in this order:
/path/to/myproject/polls/templates/foo.html
/path/to/myproject/music/templates/foo.html
Note that the loader performs an optimization when it is first imported: it caches a list of which INSTALLED_APPS packages have a templates subdirectory.
This loader is enabled by default.
django.template.loaders.eggs.load_template_source: This loader is just like app_directories, except it loads templates from Python eggs rather than from the filesystem. This loader is disabled by default; you’ll need to enable it if you’re using eggs to distribute your application. (Python eggs are a way of compressing Python code into a single file.)
Django uses the template loaders in order according to the TEMPLATE_LOADERS setting. It uses each loader until a loader finds a match.
Extending the Template System
custom template tags and/or filters
Creating a Template Library
to create a template library – a small bit of infrastructure Django can hook into.
- First, create another app solely for the template library. because your filters might be useful to you in future projects, add the app to your INSTALLED_APPS setting
- Second, create a templatetags directory in the appropriate Django application’s package. It should be on the same level as models.py, views.py, and so forth. For example:
- __init__.py and then your custom tag/filter defintions
books/
__init__.py
models.py
templatetags/ __init__.py; poll_extras.py etc.
views.py
correspond to the poll_extras.py # your custom defined tag/filter{% load poll_extras %} //later loading in the template
The {% load %} tag looks at your INSTALLED_APPS setting (new app for template library must be added in setting)and only allows the loading of template libraries within installed Django applications. This is a security feature; it allows you to host Python code for many template libraries on a single computer without enabling access to all of them for every Django installation.
first thing in poll_extras.py is registration:
from django import template register = template.Library()Later:
register.filter('cut', cut)
register.filter('lower', lower)
Writing Custom Template Filters
- __init__.py inside app folder, and inside templatetags folder (under yourApp folder)
- app name in the INSTALLED_APPS section from settings.py
- to use: {% load customizedfilter %}s
Custom filters are just Python functions that take one or two arguments:
- The value of the variable (input)
- The value of the argument, which can have a default value or be left out altogether
Rule for filter functions:
. They shouldn’t raise exceptions, and they should fail silently. If there’s an error, they should return either the original input or an empty string
def cut(value, arg): "Removes all values of arg from the given string" return value.replace(arg, '')
{{ somevariable|cut:" " }}
def lower(value): # Only one argument. "Converts a string into all lowercase" return value.lower()
register.filter('cut', cut) register.filter('lower', lower)
using decorator
donefrom django import template register = template.Library() @register.filter #OR @register.filter(name='cut') def cut(value, arg): return value.replace(arg, '')
Writing Custom Template Tags
When Django compiles a template, it splits the raw template text into nodes. Each node is an instance of django.template.Node and has a render() method. Thus, a compiled template is simply a list of Node objects. For example, consider this template:
Hello, {{ person.name }}.
{% ifequal name.birthday today %}
Happy birthday!
{% else %}
Be sure to come back on your birthday
for a splendid surprise message.
{% endifequal %}
In compiled template form, this template is represented as this list of nodes:
- Text node: "Hello, "
- Variable node: person.name
- Text node: ".\n\n"
- IfEqual node: name.birthday and today
Thus, to define a custom template tag, you specify how the raw template tag is converted into a Node (the compilation function) and what the node’s render() method does.
1 Writing the Compilation Function
For each template tag the parser encounters, it calls a Python function with the tag contents and the parser object itself. This function is responsible for returning a Node instance based on the contents of the tag.{% xxx %} parser
User-defined {% current_time %} #actually available: {% now %}
<p>The time is {% current_time "%Y-%m-%d %I:%M %p" %}.</p>
token.contents is a string of the raw contents of the tag. In our example, it’s'current_time "%Y-%m-%d %I:%M %p"'.
from django import template register = template.Library() def do_current_time(parser, token): try: # split_contents() knows not to split quoted strings. tag_name, format_string = token.split_contents() except ValueError: msg = '%r tag requires a single argument' % token.split_contents()[0] raise template.TemplateSyntaxError(msg) return CurrentTimeNode(format_string[1:-1])
parser is the template parser object. We don’t use it in this example. token is the token currently being parsed by the parser.
- Don’t hard-code the tag’s name in your error messages, because that couples the tag’s name to your function. token.split_contents()[0] will always be the name of your tag – even when the tag has no arguments.
- The function returns a CurrentTimeNode (which we’ll create shortly) containing everything the node needs to know about this tag. In this case, it just passes the argument "%Y-%m-%d %I:%M %p". The leading and trailing quotes from the template tag are removed with format_string[1:-1].
- Template tag compilation functions must return a Node subclass; any other return value is an error.
2 Writing the Template Node
import datetime class CurrentTimeNode(template.Node): #extends def __init__(self, format_string): self.format_string = str(format_string) def render(self, context): now = datetime.datetime.now() return now.strftime(self.format_string)
3 Registering the Tag
register.tag('current_time', do_current_time)As with filter registration, it is also possible to use register.tag as a decorator in Python 2.4 and above:
@register.tag(name="current_time") def do_current_time(parser, token): # ... @register.tag def shout(parser, token): # ...
------------------------------------------------------------------------------------------------
Setting a Variable in the Context
The previous section’s example simply returned a value. Often it’s useful to set template variables instead of returning values.
return a value vs. set a value
dictionary assignment
class CurrentTimeNode2(template.Node): def __init__(self, format_string): self.format_string = str(format_string) def render(self, context): now = datetime.datetime.now() context['current_time'] = now.strftime(self.format_string) return ''
Note that render() returns an empty string. render() should always return a string, so if all the template tag does is set a variable, render() should return an empty string.
New version: setting template variable through context dictionary
(hard-coded)
To do so:
Template tags can work as blocks containing other tags (like {% if %}, {% for %}, etc.). To create a template tag like this, use parser.parse() in your compilation function.{% current_time2 "%Y-%M-%d %I:%M %p" %} <p>The time is {{ current_time }}.</p>(non hard-coded)
{% get_current_time "%Y-%M-%d %I:%M %p" as my_current_time %}
<p>The current time is {{ my_current_time }}.</p>
To do so:import re class CurrentTimeNode3(template.Node): def __init__(self, format_string, var_name): self.format_string = str(format_string) self.var_name = var_name def render(self, context): now = datetime.datetime.now() context[self.var_name] = now.strftime(self.format_string) return '' def do_current_time(parser, token): # This version uses a regular expression to parse tag contents. try: # Splitting by None == splitting by spaces. tag_name, arg = token.contents.split(None, 1) except ValueError: msg = '%r tag requires arguments' % token.contents[0] raise template.TemplateSyntaxError(msg) m = re.search(r'(.*?) as (\w+)', arg) if m: fmt, var_name = m.groups() else: msg = '%r tag had invalid arguments' % tag_name raise template.TemplateSyntaxError(msg) if not (fmt[0] == fmt[-1] and fmt[0] in ('"', "'")): msg = "%r tag's argument should be in quotes" % tag_name raise template.TemplateSyntaxError(msg) return CurrentTimeNode3(fmt[1:-1], var_name)
Re: Regular expression operations
Parsing Until Another Template Tag
Comment Tag:
def do_comment(parser, token): nodelist = parser.parse(('endcomment',)) #parse until; return nodeList parser.delete_first_token() # not counting {% comment %} and {% endcomment %} return CommentNode() class CommentNode(template.Node): def render(self, context): return ''
parser.parse() takes a tuple of names of template tags to parse until. It returns an instance ofdjango.template.NodeList, which is a list of all Node objects that the parser encountered before it encountered any of the tags named in the tuple.
So in the preceding example, nodelist is a list of all nodes between {% comment %} and {% endcomment %}, not counting {% comment %} and {% endcomment %} themselves.
After parser.parse() is called, the parser (not nodeList from parser.parse) hasn’t yet “consumed” the {% endcomment %} tag, so the code needs to explicitly call parser.delete_first_token() to prevent that tag from being processed twice.
Parsing Until Another Template Tag and Saving Contents {% endXXXX %}
{% upper %}
This will appear in uppercase, {{ user_name }}.
{% endupper %}
def do_upper(parser, token):
nodelist = parser.parse(('endupper',))
parser.delete_first_token()
return UpperNode(nodelist)
class UpperNode(template.Node):
def __init__(self, nodelist):
self.nodelist = nodelist
def render(self, context):
output = self.nodelist.render(context) #calls render() one each node
return output.upper()
The only new concept here is self.nodelist.render(context) in UpperNode.render(). This simply calls render() on eachNode in the node list.
{% upper %} This will appear in uppercase, {{ user_name }}. {% endupper %}
def do_upper(parser, token):
nodelist = parser.parse(('endupper',))
parser.delete_first_token()
return UpperNode(nodelist)
class UpperNode(template.Node):
def __init__(self, nodelist):
self.nodelist = nodelist
def render(self, context):
output = self.nodelist.render(context) #calls render() one each node
return output.upper()
The only new concept here is self.nodelist.render(context) in UpperNode.render(). This simply calls render() on eachNode in the node list.Shortcut for Simple Tags
def current_time(format_string): try: return datetime.datetime.now().strftime(str(format_string)) except UnicodeEncodeError: return '' register.simple_tag(current_time)
@register.simple_tag
def current_time(token):
# ...
- Single: Only the (single) argument is passed into our function.
- Error Checking: Checking for the required number of arguments has already been done by the time our function is called, so we don’t need to do that.
- Strip: The quotes around the argument (if any) have already been stripped away, so we receive a plain Unicode string.
Inclusion Tags
effect:
{% books_for_author author %}
result in
<ul> <li>The Cat In The Hat</li> <li>Hop On Pop</li> <li>Green Eggs And Ham</li> </ul>
1. function
def books_for_author(author): books = Book.objects.filter(authors__id=author.id) return {'books': books}
2. Template
<ul> {% for book in books %} <li>{{ book.title }}</li> {% endfor %} </ul>
3. Register
register.inclusion_tag('book_snippet.html')(books_for_author)shortcut:
@register.inclusion_tag('book_snippet.html') def books_for_author(author): # ...
>>>
takes_context: Sometimes, your inclusion tags need access to values from the parent template’s context@register.inclusion_tag('link.html', takes_context=True) def jump_link(context): return { 'link': context['home_link'], 'title': context['home_title'], }
link.html template:
Jump directly to <a href="{{ link }}">{{ title }}</a>.use the inclusion tag:
{% jump_link %}
Writing Custom Template Loaders
special loading logic. For example, you could load templates from a database, or directly from a Subversion repository using Subversion’s Python bindings, or (as shown shortly) from a ZIP archive.to be continued...
http://www.djangobook.com/en/2.0/chapter09.html
done
Subscribe to:
Posts (Atom)