Showing posts with label django. Show all posts
Showing posts with label django. Show all posts

Monday, October 2, 2017

Django - 028 - Creating an app


To start a project we use the django-admin:

~/my-django-project $ django-admin startproject mywebsite
~/my-django-project $ ls
mywebsite
~/my-django-project $ cd mywebsite/
~/my-django-project/mywebsite $ tree
.
|-- manage.py
`-- mywebsite
    |-- __init__.py
    |-- settings.py
    |-- urls.py
    `-- wsgi.py

1 directory, 5 files
~/my-django-project/mywebsite $ 

To start create a app in django we use the startapp command:

~/my-django-project/mywebsite $ python manage.py startapp mymusic
~/my-django-project/mywebsite $ tree
.
|-- db.sqlite3
|-- manage.py
|-- mymusic
|   |-- admin.py
|   |-- apps.py
|   |-- __init__.py
|   |-- migrations
|   |   `-- __init__.py
|   |-- models.py
|   |-- tests.py
|   `-- views.py
`-- mywebsite
    |-- __init__.py
    |-- __init__.pyc
    |-- settings.py
    |-- settings.pyc
    |-- urls.py
    |-- urls.pyc
    |-- wsgi.py
    `-- wsgi.pyc

3 directories, 17 files
~/my-django-project/mywebsite $ cd ..
~/my-django-project $ tree
.
`-- mywebsite
    |-- db.sqlite3
    |-- manage.py
    |-- mymusic
    |   |-- admin.py
    |   |-- apps.py
    |   |-- __init__.py
    |   |-- migrations
    |   |   `-- __init__.py
    |   |-- models.py
    |   |-- tests.py
    |   `-- views.py
    `-- mywebsite
        |-- __init__.py
        |-- __init__.pyc
        |-- settings.py
        |-- settings.pyc
        |-- urls.py
        |-- urls.pyc
        |-- wsgi.py
        `-- wsgi.pyc

4 directories, 17 files
~/my-django-project $ 







Saturday, July 1, 2017

Django - 027 - Philosophies and Limitations

First and foremost, the limitations to the DTL (Django Template Language) are intentional.

Django was developed in the high volume, ever-changing environment of an online newsroom. The original creators of Django had a very definite set of philosophies in creating the DTL.

These philosophies remain core to Django today. They are:

  1. Separate Logic from presentation
  2. Discourage redundancy
  3. Be decoupled from HTML
  4. XML is bad
  5. Assume designer competence
  6. Treat whitespace obviously
  7. Don't invent a programming language
  8. Ensure safety and security
  9. Extensible


Following is the explanation for this:

1. Separate Logic from Presentation:
A template system is a tool that controls presentation and presentation related logic and that is it. The template system should not support functionality that goes beyond this basic goal.

2. Discourage Redundancy:
The majority of dynamic websites use some sort of common site-wide design - a common header, footer, navigation bar and so on. The Django template system should make it easy to store those elements in a single place, eliminating duplicate code. This is the philosophy behind template inheritance.

3. Be decoupled from HTML:
The template system should not be designed so that it only outputs HTML. It should be equally good at generating other text based formats, or just plain text.

4. XML should not be used for template languages:
Using an XML engine to parse templates introduces a whole new world of human error in editing templates - an incurs an unacceptable level of overhead in template processing.

5. Assume Designer comptance:
The template system should not be designed so that templates necessarily are displayed nicely in WYSIWYG editors such as Dreamweaver. That is too severe of a limitation and wouldn't allow the syntax to be as nice as it is.

Django expects template authors are comfortable editing HTML directly.

6. Treat whitespace obviously:
The template system should not do magic things with whitespace. If a template includes whitespace, the system should treat the whitespace as it treats text-just display it. Any whitespace that is not in a template tag should be displayed.

7. Do not invent a programming language:
The template system intentionally does not allow the following:
Assignment to variables.
Advanced Logic

The goal is not to invent a programming language. The goal is to offer just enough programming-esque functionality, such as branching and looping, it is essential for making presentation related decisions.

The Django template system recognizes that templates are most often written by designers, not programmers, and therefore should not assume Python knowledge.

8. Safety and Security:
The template system, out of the box, should forbid the inclusion of malicious code - such as commands that delete database records. This is another reason the template system does not allow arbitrary Python code.

9. Extensibility:
The template system should recognize that advanced template authors may want to extend its technology. This is the philosophy behind custom template tags and filters.

When the pressure is on to GetStuffDone, and you have both designers and programmers trying to communicate and get all of the last minute tasks done, Django just gets out of the way and lets each team concentrate on what they are good at.

Once you have found this out for yourself through real-life practice, you will find out very quickly why Django really is the framework for perfectionists with deadlines.

With all this in mind, Django is flexible - it does not require you to use the DTL. More than any other component of web applications, template syntax is highly subjective, and programmers opinions vary wildly. The fact that Python alone has dozens, if not hundreds, of open-source template-language implementations supports this point. Each was likely created because its developer deemed all existing template-languages inadequate.

Because Django is intended to be a full-stack web framework that provides all the pieces necessary for web developers to be productive, most times it is more convenient to use the DTL, but it is not a strict requirement in any sense.


Monday, January 16, 2017

Django - 026 - How invalid variables are handled

Generally, if a variable does not exist, the template system inserts the value of the engine's string_if_invalid configuration option, which is an empty string by default. For example:

$ python manage.py shell -i python
Python 2.7.10 |Anaconda 2.3.0 (64-bit)| (default, May 28 2015, 17:02:03) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.template import Template,Context
>>> t = Template("Your name is {{name}}.")
>>> t.render(Context())
u'Your name is .'
>>> t.render(Context({'var':'Sandhya'}))
u'Your name is .'
>>> t.render(Context({'NAME':'Sandhya'}))
u'Your name is .'
>>> t.render(Context({'Name':'Sandhya'}))
u'Your name is .'
>>> 
This behavior is better than raising an exception because it is intended to be resilient to human error. In this case, all of the lookups failed because variable names have the wrong case or name. In the real world, it is unacceptable for a web site to become inaccessible due to a small template syntax error.

Sunday, January 15, 2017

Django - 025 - Method Call Behavior

Method calls are slightly more complex than the other lookup types. Here are some things to keep in mind:

If, during the method lookup, a method raises an exception, the exception will be propagated, unless the exception has an attribute silent_variable_failure whose value is True. If the exception does have a silent_variable_failure attribute, the variable will render as the value of the engine's string_if_invalid configuration option (an empty string by default). For example:

$ python manage.py shell -i python
Python 2.7.10 |Anaconda 2.3.0 (64-bit)| (default, May 28 2015, 17:02:03) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.template import Template,Context
>>> t = Template("My name is {{ person.first_name  }}.")
>>> class PersonClass3:
...    def first_name(self):
...       raise AssertionError("foo")
... 
>>> p = PersonClass3()
>>> t.render(Context({"person":p}))
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/opt/anaconda/lib/python2.7/site-packages/django/template/base.py", line 208, in render
    return self._render(context)
  File "/opt/anaconda/lib/python2.7/site-packages/django/template/base.py", line 199, in _render
    return self.nodelist.render(context)
  File "/opt/anaconda/lib/python2.7/site-packages/django/template/base.py", line 994, in render
    bit = node.render_annotated(context)
  File "/opt/anaconda/lib/python2.7/site-packages/django/template/base.py", line 961, in render_annotated
    return self.render(context)
  File "/opt/anaconda/lib/python2.7/site-packages/django/template/base.py", line 1044, in render
    output = self.filter_expression.resolve(context)
  File "/opt/anaconda/lib/python2.7/site-packages/django/template/base.py", line 711, in resolve
    obj = self.var.resolve(context)
  File "/opt/anaconda/lib/python2.7/site-packages/django/template/base.py", line 852, in resolve
    value = self._resolve_lookup(context)
  File "/opt/anaconda/lib/python2.7/site-packages/django/template/base.py", line 915, in _resolve_lookup
    current = current()
  File "<console>", line 3, in first_name
AssertionError: foo
>>> class SilentAssertionError(Exception):
...    silent_variable_failure = True
... 
>>> class PersonClass4:
...   def first_name(self):
...       raise SilentAssertionError
... 
>>> p = PersonClass4()
>>> t.render(Context({"person":p}))
u'My name is .'
>>> 
  • A method call will only work if the method has no required arguments. Otherwise, the system will move to the next lookup type (list-index lookup).
  • By design, Django intentionally limits the amount of logic processing available in the template, so it is not possible to pass arguments to method calls accessed from within templates. Data should be calculated in views and then passed to templates for display.
  • Obviously, some methods have side-effects, and it would be foolish at best, and possibly even a security hole, to allow the template system to access them.
  • Say, for instance, you have a BankAccount object that has a delete() method. If a template includes something like {{ account.delete }}, where account is BankAccount object, the object would be deleted when the template is rendered! To prevent this, set the function attribute alters_data on the method:
    >>> def data(self):
    ...   # Delete the account
    ...   delete.alters_data = True
    ...
    >>>
  • The Template system won't execute any method marked in this way. Continuing the preceding example, if a template includes {{ account.delete }} and the delete method has the alters_data = True, then the delete() method will not be executed when the template is rendered, the engine will instead replace the variable with string_if_invalid.
  • NOTE: The dynamically-generated delete() and save() methods on Django model objects get alters_data=true set automatically.


Thursday, January 12, 2017

Django - 024 - Context Variable Lookup

In the examples so far, we have passed simple values in the contexts - mostly strings, plus a datetime.date example. However, the template system elegantly handles more complex data structures, such as lists, dictionaries and custom objects. The key to traversing complex data structures in Django templates is the dot character ("."):

Use a dot to access dictionary keys, attributes, methods, or indices of an object. This is best illustrated with a few examples. For instance, suppose you are passing a Python dictionary to a template. To access the values of that dictionary by dictionary key, use a dot:

 $ python manage.py shell -i python
Python 2.7.10 |Anaconda 2.3.0 (64-bit)| (default, May 28 2015, 17:02:03)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.template import Template, Context
>>> person = {'name': 'Lakshmi', 'age':32}
>>> t = Template('{{person.name}} is {{person.age}} years old.')
>>> c = Context({'person':person})
>>> print t.render(c)
Lakshmi is 32 years old.
>>>

Similarly, dots also allow access to object attributes. For example, a Python datetime.date  object has year, month and day attributes, and you can use a dot to access those attributes in a Django template:

$ python manage.py shell -i python
Python 2.7.10 |Anaconda 2.3.0 (64-bit)| (default, May 28 2015, 17:02:03)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.template import Template, Context
>>> import datetime
>>> d = datetime.date(2014,4,1)
>>> d.year
2014
>>> d.month
4
>>> d.day
1
>>> t = Template('The month is {{date.month}} and the year is {{date.year}}.')
>>> c = Context({'date':d})
>>> t.render(c)
The month is 4 and the year is 2014.
>>> 

This example uses a custom class, demonstrating that variable dots also allow attribute access on arbitrary objects:

$ python manage.py shell -i python
Python 2.7.10 |Anaconda 2.3.0 (64-bit)| (default, May 28 2015, 17:02:03)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.template import Template,Context
>>> class Person(object):
...    def __init__(self, first_name, last_name):
...        self.first_name, self.last_name = first_name, last_name
...
>>> t = Template('Hello, {{person.first_name}} {{person.last_name}}.')
>>> c = Context({'person':Person('Sandhya','Kulkarni')})
>>> print t.render(c)
Hello, Sandhya Kulkarni.
>>> 

Dots can also refer to methods of objects. For example, each Python string has the methods upper() and isdigit() , and you can call those in Django templates using the same dot syntax:

$ python manage.py shell -i python
Python 2.7.10 |Anaconda 2.3.0 (64-bit)| (default, May 28 2015, 17:02:03)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.template import Template, Context
>>> t = Template('{{var}} -- {{var.upper}}  -- {{var.isdigit}}')    
>>> t.render(Context({'var':'123'}))
u'123 -- 123  -- True'
>>>

Note that you do not include parenthesis in the method calls. Also, it is not possible to pass arguments to the methods; you can only call methods that have no required arguments. 

Finally, dots are also used to access list indices, for example:
$ python manage.py shell -i python
Python 2.7.10 |Anaconda 2.3.0 (64-bit)| (default, May 28 2015, 17:02:03)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.template import Template,Context
>>> t = Template('Item 2 is {{items.2}}.')
>>> c = Context({'items':['apples','bananas','carrots']})
>>> print t.render(c)
Item 2 is carrots.
>>>
Negative list indices are not allowed. For example, the template variable

{{items.-1}} would cause a TemplateSyntaxError.

Python Lists
A reminder, Python lists have 0-based indices. The first item is at index 0, the second is at index 1, and so on.
Dot lookups can be summarized like this: when the template system encounters a dot in a variable name, it tries the following lookups, in this order:

  • Dictionary Lookup (for example, foo["bar"])
  • Attribute Lookup (for example, foo.bar)
  • Method Call (for example, foo.bar())
  • List-index lookup (for example, foo[2])

The system uses the first lookup type that works. It is short-circuit logic. Dot lookups can be nested multiple levels deep. For instance, the following example uses {{person.name.upper}} , which translates into a dictionary lookup (person['name']) and then a method call (upper()):

$ python manage.py shell -i python
Python 2.7.10 |Anaconda 2.3.0 (64-bit)| (default, May 28 2015, 17:02:03)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.template import Template,Context
>>> person = {'name':'Sandhya','age':'32'}
>>> t = Template('{{ person.name.upper }} is {{person.age}} years old.')
>>> c = Context({'person':person})
>>> print t.render(c)
SANDHYA is 32 years old.


Django - 023 - Multiple Contexts, same template

Once you have a Template object, you can render multiple contexts through it. For example:

 $ python manage.py shell -i python
Python 2.7.10 |Anaconda 2.3.0 (64-bit)| (default, May 28 2015, 17:02:03) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.template import Template, Context
>>> t = Template('Hello, {{name}}')
>>> print t.render(Context({'name' : 'Mahesh'}))
Hello, Mahesh
>>> print t.render(Context({'name' : 'Ganesh'}))
Hello, Ganesh
>>> print t.render(Context({'name' : 'Saraswati'}))
Hello, Saraswati
>>> 


Whenever you are using the same template source to render multiple contexts like this, it is more efficient to create the Template object once, and then call render() on it multiple times:

>>> #bad practice - template inside the for loop
>>> for name in ('Mahesh','Ganesh','Saraswati'):
...    t = Template('Hello, {{name}}')
...    t.render(Context({'name' : name}))
...
u'Hello, Mahesh'
u'Hello, Ganesh'
u'Hello, Saraswati'
>>> 

>>> #good practice - template outside the for loop
>>> t = Template('Hello, {{name}}')
>>> for name in ('Mahesh','Ganesh','Saraswati'):
...    print t.render(Context({'name' : name}))
... 
Hello, Mahesh
Hello, Ganesh
Hello, Saraswati
>>> 

Django's template parsing is quite fast. Behind the scenes, most of the parsing happens via a call to a single-regular expression. This is stark contrast to XML based template engines, which incur the overhead of an XML parser and tend to be orders of magnitude slower than Django's template rendering engine.

Wednesday, January 11, 2017

Django - 022 - Dictionaries and contexts

A Python dictionary is a mapping between known keys and variable values. A context is similar to a dictionary, but a Context provides additional functionality.

Variable names must begin with a letter (A-Z or a-z) and may contain more letters, digits, underscores and dots. (Dots are a special case we will get to in a moment.) Variable names are case sensitive. Here is an example of template compilation and rendering, using a template similar to the example previously shown:
~/Documents/my_d3_project/django/myD3site $ python manage.py shell -i python
Python 2.7.10 |Anaconda 2.3.0 (64-bit)| (default, May 28 2015, 17:02:03) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.template import Template, Context
>>> raw_template = """ <p> Dear {{person_name}}, </p>
... 
... <p> Thanks for placing an order from {{company}}. It's scheduled to 
... ship on {{ ship_date|date:"F j, Y"}}.</p>
... 
... {%if ordered_warranty%}
... <p> Your warranty information will be included in the packaging. </p>
... {% else %}
... <p> You did not order a warranty, so you are on your own when the products
... inevitably stop working. </p>
... {% endif %}
... 
... <p>Sincerely, <br /> {{company}} </p> """
>>> t = Template(raw_template)
>>> import datetime
>>> c = Context({'person_name':'Siddharth Mehta',})
>>> c = Context({'person_name':'Siddharth Mehta',  
...     'company':'Outdoor Equipment',
...     'ship_date':datetime.date(2017,1,8),
...     'ordered_warranty':False})
>>> t.render(c)
u" <p> Dear Siddharth Mehta, </p>\n\n<p> Thanks for placing an order from Outdoor Equipment. It's scheduled to\nship on January 8, 2017.</p>\n\n\n<p> You did not order a warranty, so you are on your own when the products\ninevitably stop working. </p>\n\n\n<p>Sincerely, <br /> Outdoor Equipment </p> "
>>> 

  • First, we import the classes Template and Context, which both live in the module django.template.
  • We save the raw text of our template into the variable raw_template. Note that we use triple quote marks to designate the string, because it wraps over multiple lines; in contrast, string within single quote marks cannot be wrapped over multiple lines.
  • Next, we create a template object, t, by passing raw_template to the Template class constructor.
  • We import the datetime module from Python's standard library, because we will need it in the following statement.
  • Then, we create a context object, c. The Context constructor takes a Python dictionary, which maps variable names to values. Here, for example, we specify that the person_name is "John Smith", company is "Outdoor equipment", and so forth.
  • Finally, we call the render() method on our template object, passing it the context. This returns the rendered template - that is, it replaces template variables with the actual values of the variables, and it executes any template tags. 


Note that you did not order a warranty paragraph was displayed because the ordered_warranty variable evaluated to False. Also, note the date:  January 8, 2017 which was displayed according to the format string "F j, Y".

If you are new to Python, you may wonder why this output includes newline characters ("\n") rather than displaying line breaks. That is happening because of a subtlety in the Python interactive interpreter: the call to t.render(c) returns a string, and by default the interactive interpreter displays the representation  of the string, rather than the printed value of the string. If you want to see the string with line breaks displayed as true line breaks rather than "\n" characters, use the print function:
print t.render(c)

These are the fundamentals of using the Django template system: just write a template string, create a Template object, create a Context, and call the render method.


Sunday, January 8, 2017

Django - 021 - Rendering a Template

Once you have a Template object, you can pass it data by giving it a context. A context is simply a set of template variable names and their associated values. A template uses this to populate its variables and evaluate its tags. a context is represented in Django by the Context class, which lives in the django.template module. Its constructor takes one optional argument: a dictionary mapping variable names to variable values.

Call the Template object's render() method with the context to fill the template:

 ~/Documents/my_d3_project/django/myD3site $ python manage.py shell
Python 2.7.10 |Anaconda 2.3.0 (64-bit)| (default, May 28 2015, 17:02:03) 
Type "copyright", "credits" or "license" for more information.

IPython 3.2.0 -- An enhanced Interactive Python.
Anaconda is brought to you by Continuum Analytics.
Please check out: http://continuum.io/thanks and https://anaconda.org
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: from django.template import Context, Template

In [2]: t = Template("My name is {{name}}.")

In [3]: c = Context({'name':'Basavaraj'}) 

In [4]: t.render(c)
Out[4]: u'My name is Basavaraj.'

In [5]: 

A special Python prompt:
If you have used Python before, you maybe wondering why we are running python manage.py shell instead of just python (or python3). Both commands will start the interactive interpreter, but the manage.py shell command has one key difference: before starting the interpreter, it tells Django which settings file to use.

Many parts of Django, including the template system, rely on your settings and you won't be able to use them unless the framework knows which settings to use.

If you are curious, here is how it works behind the scenes. Django looks for an environment variable called DJANGO_SETTINGS_MODULE, which should be set to the import path of your settings.py. For example, DJANGO_SETTINGS_MODULE might be set to 'myD3site.settings', assuming myD3site is on your Python path.

When you run python manage.py shell, the command takes care of setting DJANGO_SETTINGS_MODULE for you. You will need to use python manage.py shell in these examples or Django will throw an exception.

Django - 020 - Creating Template Objects

The easiest way to create a Template object is to instantiate it directly. The Template class lives in the django.template module, and the constructor takes one argument, the raw template code. Let us dip into Python interactive interpreter to see how this works in code. From the myD3site project directory type python manage.py shell to start the interactive interpreter.

Let us go through some template system basics:
~/Documents/my_d3_project/django/myD3site $ python manage.py shell
Python 2.7.10 |Anaconda 2.3.0 (64-bit)| (default, May 28 2015, 17:02:03) 
Type "copyright", "credits" or "license" for more information.

IPython 3.2.0 -- An enhanced Interactive Python.
Anaconda is brought to you by Continuum Analytics.
Please check out: http://continuum.io/thanks and https://anaconda.org
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: from django.template import Template

In [2]: t = Template("My name is {{name}}.")

In [3]: print t
<django.template.base.Template object at 0x7ffb203109d0>

In [4]: 


The 0x7ffb203109d0 will be different everytime, and it is not relevant; it is a Python thing (the Python "identity" of the Template object, if you must know.)

When you create a template object, the template system compiles the raw template code into an internal, optimized form, ready for rendering. But if your template code includes any syntax errors, the call to Template() will cause a TemplateSyntaxError exception:

In [1]: from django.template import Template

In [2]: t = Template('{% notatag %}')
---------------------------------------------------------------------------
TemplateSyntaxError                       Traceback (most recent call last)
<ipython-input-2-fdd5f59f5346> in <module>()
----> 1 t = Template('{% notatag %}')
TemplateSyntaxError: Invalid block tag on line 1: 'notatag'. Did you forget to register or load this tag?

The term "block tag" here refers to {% notatag %}. Block Tag and "Template Tag" are synonymous. The system raises a TemplateSyntaxError exception for any of the following cases:

  • Invalid Tags
  • Invalid arguments to valid tags
  • Invalid filters
  • Invalid arguments to valid filters
  • Invalid template syntax
  • Unclosed tags (for tags that require closing tags)



Django - 019 - Using the template system

A Django project can be configured with one or several template engines (or even zero if you don't use templates). Django ships with a built in backend for its own template system the Django Template Language (DTL) . Django 1.10 also includes support for the popular alternative Jinja2 (for more information visit http://jinja.pocoo.org/). If you do not have a pressing reason to choose another backend, you should use the DTL - especially if you are writing a pluggable application and you intend to distribute templates. Django's contrib apps that include templates, like django.contrib.admin, use the DTL. Here is the most basic way you can use Django's template system in Python code:
  1. Create a Template object by providing the raw template code as a string.
  2. Call the render() method of the Template object with a given set of variables (the context). This returns a fully rendered template as a string, with all of the variables and template tags evaluated according to the context.

In code, here is what that looks like:

~/Documents/my_d3_project/django/myD3site $ python manage.py shell
Python 2.7.10 |Anaconda 2.3.0 (64-bit)| (default, May 28 2015, 17:02:03) 
Type "copyright", "credits" or "license" for more information.

IPython 3.2.0 -- An enhanced Interactive Python.
Anaconda is brought to you by Continuum Analytics.
Please check out: http://continuum.io/thanks and https://anaconda.org
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: from django import template

In [2]: t = template.Template("My name is {{name}}.")

In [3]: c = template.Context({'name':'Sashank'})

In [4]: print t.render(c)
My name is Sashank.

In [5]: 

Next, let us describe each step in more detail.

Referencehttp://stackoverflow.com/questions/18081369/error-when-using-django-template

Django - 018 - Template system basics

A Django template is a string of text that is intended to separate the presentation of a document from its data. A template defines placeholders and various bits of basic logic (template tags) that regulate how the document should be displayed. Usually, templates are used for producing, HTML, but Django templates are equally capable of generating any text-based format.

Philosophy behind Django templates
If you have a background in programming, or if you are used to languages which mix programming code directly into HTML, you will want to bear in mind that the Django template system is not simply Python embedded into HTML.

This is by design: the template system is meant to express presentation, not programming logic.

Let us start with a single example template. This Django template describes an HTML page that thanks a person for placing an order with a company. Think of it as a form letter:

<html>
<head> <title> Ordering notice </title> </head>
<body>
<h1> Ordering Notice </h1>
<p> Dear {{ person_name }},</p>
<p> Thanks for placing an order from {{ company }}. It is scheduled to ship on {{ ship_date|date:"F j, Y" }} . </p>
<p> Here are the item's you have ordered: </p>
<ul> 
{% for item in item_list %} <li> {{item}} <li> {% endfor %}
</ul>

{% if ordered_warrantly %}
 <p> Your warranty information will be included in the packaging.  </p>
{% else %}
 <p> You did not order a warranty, so you are on your own when the products inevitably stop working.</p>
{% endif%}
<p> Sincerely, <br/> {% company %} </p>

</body>
</html>
This template is basic HTML with some variables and template tags thrown in. Let us step through it:

Any text surrounded with a pair of braces (for example, {{person_name}} ) is a variable. This means "insert the value of the variable with the given name". How do we specify the values of the variables? We will get to that in a moment. Any text that is surrounded by curly braces and percent signs (for example, {% if ordered_warrantly %}) is a template tag. The definition of a tag is quite broad: a tag just tells the template system to "do something".
This example template contains a for tag ({% for item in item_list %}) and a if tag ({% if ordered_warrantly %}). A for tag works very much like a for statement in Python, letting you loop over each item in a sequence.
An if tag, as you may expect, acts as a logical if statement. In this particular case, the tag checks whether the value of the ordered_warranty variable evaluates to True. If it does, the template system will display everything between the {% if ordered_warrantly %} and {% else %} . If not, the template system will display everythin between the {% endif%} and  {% endif%}. Note that the {% else %}  is optional.
Finally, the second paragraph of this template contains an example of a filter, which is the most convenient way to alter the formatting of a variable. In this example, {{ ship_date|date:"F j, Y" }} , we are passing the ship_date variable to the date filter, giving the date filter the argument "F j, Y". The date filter formats dates in a given format, as specified by that argument. Filters are attached using a pipe character (|) , as a reference to Unix pipes.

Each Django template has access to several built-in tags and filters. It is a good idea to familiarize yourself with that list so you know what is possible. It is also possible to create your own filters and tags.



Django - 017 - Templates Introduction

Till now, we have been hard coding HTML directly in our Python code, like this:

def current_datetime(request):
  now = datetime.datetime.now()
  html = "<html> <body>  It is now %s. </body></html>" %now
  return HttpResponse(html)

Although this technique was convenient for the purpose of explaining how views work, it is not a good idea to hard-code HTML directly into our views. Here is why:


  • Any change to the design of the page requires a change to the Python code. The design of a site tends to change far more frequently than the underlying Python code, so it would be convenient if the design could change without needing to modify the Python code.
  • This is only a very simple example. A common webpage template has hundreds of lines of HTML and scripts. Untangling and troubleshooting program code from this mess is a nightmare. (cough-PHP-cough)
  • Writing Python code and designing HTML are two different disciplines, and most professional web-development environments split these responsibilities between separate people (or even separate departments). Designers and HTML/CSS coders shouldn't be required to edit Python code to get their job done.
  • It is most efficient if programmers can work on Python code and designers can work on templates at the same time, rather than one person waiting for the other to finish editing a single file that contains both Python and HTML.


For these reasons, it is much cleaner and more maintainable to separate the design of the page from the Python code itself. We can do this with Django's template system, which we discuss further.

Django - 016 - What is next?

So far, we have been writing our view functions with HTML hard-coded directly in the Python code. I have done that to keep things simple while I demonstrated core concepts, but in the real world, this is nearly always a bad idea. Django ships with a simple yet powerful template engine that allows you to separate the design of the page from the underlying code. We will dive into the Django's template engine next.

Django - 015 - Django's pretty error pages

Take moment to admire the fine web application we have made so far- now let's break it! Let us deliberately introduce a Python error into our views.py file by commenting out the
offset = int(offset) lines in the hours_ahead view:

def hours_ahead(request, offset):
  #try:
  #   offset = int(offset)
  #except ValueError:
   #  raise Http404()
  dt = datetime.datetime.now() + datetime.timedelta(hours=offset)
  html = "<html><body> In %s hour(s), it will be %s. </body></html>" % (offset,dt)
  return HttpResponse(html)

Load up the development server and navigate to /time/plus/3/. You will see an error page with a significant amount of information, including a TypeError message displayed at the very top: unsupported type for timedelta hours component: str



What happened? Well, the datetime.timedelta function expects the hours parameter to be an integer, and we commented out the bit of code that converted offset to an integer. That caused datetime.timedelta to raise the TypeError. It is the typical kind of small bug that every programmer runs into at somepoint. The point of this example was to demonstrate Django's error pages. Take some time to explore the error page and get to know the various bits of information it gives you. Here are some things to notice:

  • At the top of the page, you get the key information about the exception: the t ype of exception, any parameters to the exception (the unsupported type message in this case), the file in which the exception was raised, and the offending line number.
  • Under the key exception information, the page displays the full Python traceback for this exception. This is similar to the standard traceback you get in Python's command-line interpreter, except it is more interactive. For each level (frame) in the stack, Django displays the name of the file, the function/method name, the line number, and the source code of that line.
  • Click the line of source code (in dark gray), and you will see several lines from before and after the erroneous line, to give you context. Click Local vars under any frame in the stack to view a table of all local variables and their values , in that frame, at the exact point in the code at which the exception was raised. This debugging information can be of great help!
  • Note the switch to copy-and-paste view text under the Traceback header. Click those words, and the traceback will switch to an alternate version that can be easily copied and pasted. Use this when you want to share your exception traceback with others to get technical support - such as the kind folks in the Django IRC chat room or on the Django users mailing list. 
  • Underneath, the Share this traceback on a public website button will do this work for you in just one click. Click it to post the traceback to dpaste (for more information visit http://www.dpaste.com/), where you will get a distinct URL that you can share with other people.
  • Next, the Request information section includes a wealth of information about the incoming web request that spawned the error: GET  and POST information, cookie values, and meta information, such as CGI headers. 
  • Following to the Request Information section, the Settings section lists all of the settings for this particular Django installation.


The Django error page is capable of displaying more information in certain special cases, such as the case of template syntax errors. For now, uncomment the offset = int(offset) lines to get the view function working properly again.

The Django error page is also really useful if you are the type of programmer who likes to debug with the help of carefully placed print statements.

At any point in your view, temporarily insert an assert False to trigger the error page. Then, you can view the local variables and state of the program. Here is an example, using the hours_ahead view:

def hours_ahead(request, offset):
  try:
     offset = int(offset)
  except ValueError:
     raise Http404()
  dt = datetime.datetime.now() + datetime.timedelta(hours=offset)
  assert False
  html = "<html><body> In %s hour(s), it will be %s. </body></html>" % (offset,dt)
  return HttpResponse(html)

Finally, it is obvious that much of this information is sensitive - it exposes the innards of your Python code and Django configuration. - and it would be foolish to show this information on the public internet. A malicious person can use it to attempt to reverse-engineer your web application and do nasty things. For that reason, the Django error page is only displayed when Django project is in debug mode. For now, just know that every Django project is in debug mode automatically when you start it. (Sounds familiar? The Page not Found errors, described earlier in this chapter, work the same way.)

Saturday, January 7, 2017

Django - 014 - Our third view - dynamic URLs

In our current_datetime view, the contents of the page - the current date/time - were dynamic, but the URL (/time/) was static. In most dynamic web applications though, a URL contains parameters that influence the output of the page. For example, an online bookstore might give each book its own URL, like /books/243/ and /books/81196/. Let us create a third view that displays the current date and time one hour into the future, the page /time/plus/2/ displays the date/time two hours into the future, the page time/plus/3/ displays the date/time three hours into the future, and so on. A novice might think to code a separate view function for each hour offset, which might result in a URLconf like this:

urlpatterns = [
                 url(r'^time/$', current_datetime),
                 url(r'^time/plus/1/$', one_hour_ahead),
                 url(r'^time/plus/2/$', two_hours_ahead),
                 url(r'^time/plus/3/$', three_hours_ahead),

              ]

Clearly, this line of thought is flawed. Not only would this result in redundant view functions, but also the application is fundamentally limited to supporting only the predefined hour ranges - one, two or three hours. 

If we decided to create a page that displayed the time four hours into the future, we'd have to create a separate view and URLconf line for that, furthering the duplication. 

How, then do we design our application to handle arbitrary hour offsets? The key is to use wildcard URL patterns. As I mentioned previously, a URL pattern is a regular expression; hence, we can use the regular expression pattern \d+ to match one or more digits:

urlpatterns = [
                 #...
                 url(r'^time/plus/\d+/$', one_hour_ahead),
                 #...

              ]

This new URL pattern will match any URL such as /time/plus/4/ , /time/plus/43/ or even /time/plus/800000000/ . Come to think of it, let us limit it so that the maximum allowed offset is something reasonable.

In this example, we will set a maximum 99 hours by only allowing either one or two digit numbers - and in regular expression syntax, that translates into \d{1,2}:

url(r'^time/plus/\d{1,2}/$', hours_ahead),

Now that we've designated a wildcard for the URL, we need a way of passing that wildcard data to the view function, so that we can use a single view function for any arbitrary hour offset. We do this by placing parentheses around the data in the URLpattern that we want to save. In the case of our example, we want to save whatever number was entered in the URL, so let us put parenthesis around the \d{1,2} , like this:

url(r'^time/plus/(\d{1,2})/$', hours_ahead),

If you are familiar with regular expressions, you will be right at home here; we are using parentheses to capture data from the matched text. The final URLconf, including our previous two views, looks like this:

from django.conf.urls import include, url
from django.contrib import admin
from myD3site.views import hello
from myD3site.views import my_homepage_view , current_datetime, read_file_info, hours_ahead

urlpatterns = [

                        url(r'^admin/', include(admin.site.urls)), 
                        url(r'^hello/$', hello),
                        url(r'^$',my_homepage_view),
                        url(r'^time/$',current_datetime),
                        url(r'^fileInfo/$',read_file_info),
                        url(r'^another-time-page/$',current_datetime),
                        url(r'^time/plus/(\d{1,2})/$', hours_ahead),

]

If you are experienced in another web development platform, you may be thinking, "Hey, let us use a query string parameter!" - something like /time/plus?hours=3, in which the hours would be designated by the hours parameter in the URL's query string (the part of the '?') . You can do that with Django, but one of Django's core philosophies is that URLs should be beautiful. The URL /time/plus/3 is far cleaner, simpler, more readable, easier to recite to somebody aloud and just plain prettier than its query string counterpart. Pretty URLs are a characteristic of a quality web application. 

Django's URLconf system encourages pretty URLs by making it easier to use pretty URLs than not to.

With that taken care of, let us write the hours_ahead view. hours_ahead is very similar to the current_datetime view we wrote earlier, with a key difference: it takes an extra argument, the number of hours of offset. Here is the view code:

from django.http import HttpResponse
import datetime
import os
from django.http import Http404

def hours_ahead(request, offset):
  try:
     offset = int(offset)
  except ValueError:
     raise Http404()
     dt = datetime.datetime.now() + datetime.timedelta(hours=offset)
     html = "<html><body> In %s hour(s), it will be %s. </body></html>" % (offset,dt)

     return HttpResponse(html)


Let us take a closer look at this code.

The view function, hours_ahead, takes two parameters: request and offset:
  • request is an HttpRequest object, just as in hello and current_datetime. I will say it again: each view always takes an HttpRequest object as its first parameter. 
  • offset is the string captured by the parenthesis in the URLpattern. For example, if the requested URL were /time/plus/3/, then offset would be the string '3'. If the requested URL were /time/plus/21/, then offset would be the string '21'. Note that captured values will always be Unicode objects, not integers, even if the string is composed of only digits, such as '21'.

I decided to call the variable offset, but you can call it whatever you like, as long as it is a valid Python identifier. The variable name does not matter, all that matters is that it is the second argument to the function, after request. (It is also possible to use keyword, rather than positional, arguments in a URLconf.) 

The first thing we do within the function is call int() on offset. This converts the Unicode string value to an integer. 

Note that Python will raise a ValueError exception if you call int() on a value that cannot be converted to an integer, such as the string foo. In this example, if we encounter the ValueError, we raise the exception django.Http404, which, as you can imagine, results in a 404 Page not found error.

Astute readers will wonder: how could we ever reach the ValueError case, anyway, given that the regular expression in our URLpattern - (\d{1,2}) - captures only digits, and therefore offset will only ever be a string composed of digits?  The answer is, we won't, because the URLpattern provides a modest but useful level of input validation, but we still check for the ValueError in case this view function ever gets called in some other way.

It is good practice to implement view functions such that they do not make any assumptions about their parameters. Loose coupling, remember?

In the next line of the function, we calculate the current date/time and add the appropriate number of hours. We have already seen datetime.datetime.now() from the current_datetime view; the new concept here is that you can perform date/time arithmetic by creating a datetime.timedelta object and adding to a datetime.datetime object. Our result is stored in the variable dt.

This line also shows why we called int() on offset- the datetime.timedelta function requires the hours parameter to be an integer. 

Next, we construct the HTML output of this view function, just as we did in current_datetime. A small difference in this line from the previous line is that it uses Python's format-string capability with two values, not just one. Hence, there are two %s symbols in the string and a tuple of values to insert: (offset,dt)

Finally, we return an HttpResponse of the HTML.

With that view function and URLconf written, start the Django development server (if it is not already running), and visit http://127.0.0.1:8000/time/plus/3/ to verify it works.



Finally, visit http://127.0.01:8000/time/plus/100/ to verify that the pattern in your URLconf only accepts one or two digit numbers; Django should display a Page not Found error in this case, just as we saw in the section A quick note about 404 errors earlier.



The URL http://127.0.0.1/time/plus/(with no hour designation)  should also throw a 404.