Thursday, November 6, 2014

Django Templating Language - Part IV

OK, for this exercise, assume I have a database table (in SQLite3) that contains student names and roll numbers. Let's look at this in steps.

  1. Import everything you need in views.py:
    import sqlite3
    from django.template import Template, Context

  2. Create a data structure that will hold your records:
    class Student (object):
          def __init__ (self, name, rno):
          
          self.name = name
          
          self.rno = rno

  3. Define your view and in it extract all records of student:
    def display (request):
          conn = sqlite3.connect ("/path/to/db/dbname.db")
          cur = conn.cursor ()
          cur.execute ("select * from student")
          students = []  # Will store student records
          for row in cur:
          
          students.append (Student (row[0], row[1]))
          
          # Append to list 'students' an object of the class 'Student'

  4. Now it's time for the ol' Template/Context magic:
          t = Template ("/path/to/html/file/stud.html")
          c = Context ({'students':students})
          html = t.render (c)
          return HttpReponse (html)

  5. But we're not done yet! We don't have the HTML file in which we define how the data is to be structured:
    <html>
          {% for student in students %}
                Roll no.: {{ student.rno }}                             Name: {{ student.name }}

          {% endfor %}

    </html>

You're set! Notice how elements can be accessed in HTML using the names you defined in Python in the class Student. Neat huh? I threw a lot of information your way right now. Please comment with doubts. Until next time!

CSRF Token

I don't believe I didn't cover this before. Many of you (in fact all of you) must be getting a 'CSRF Token missing' error when you submit data using the POST method. First of all let me tell you what CSRF is.

CSRF stands for Cross Site Request Forgery. When data is submitted using the GET method, it just gets encoded in the URL. But when it is submitted using the POST method it is sent directly to the servers. During this transfer if there is some bot snooping on that site, it can intercept the data and send it's own, infected data to the site.

Anyway, coming back to Django, the solution to that error lies in Django's Templating Language. I myself am still trying to understand it. In the meantime, I found a temporary fix.
NOTE: This is a temporary fix for development websites, and should not be deployed on production websites.

Sorry for sneaking that on you like that. But it had to be done. You'll understand once I tell you how to (temporarily) fix it.

  • Open settings.py
  • Look for a tuple named MIDDLEWARE_CLASSES
  • You'll see django.middleware.csrf.CsrfViewMiddleware inclulded in it.
  • Comment that line out.

Now do you see why this is so dangerous, even though it fixes the error? You're essentially disabling Django's in built protection against CSRF (which is pretty good). NEVER deploy it on production websites. This fix is only for a temporary situation, when you want to evaluate the authenticity of some other code module.

Tuesday, November 4, 2014

Django Templating Language - Part III

We're finally here! We've already seen how to extract stuff from databases. Now let's put that to good use. Before we begin, let me explain two concepts here: Template and Context.
Template is the front end, the looks of the page. This will mean the HTML (+CSS+jQuery+whatever else) code you write.
Context means what you want to put in that page. In the earlier post, we had used the variable {{ name }}. Context will tell Python what value to pass to that variable.

First things first. Let's import the necessary stuff.
from django.template import Template, Context
from django.shortcuts import render
from django.http import HttpResponse

Now what I do is pass HTML code as string to Template make it render it. While this is a neat method, I'm sure there are others out there that I don't know. So please comment so that I'll be able to learn other (maybe more efficient) ways to render templates.
The way to do this would be to use file handling. So, in views.py:

def showName (request):
    f1 = open ("/path/to/file/something.html")
    code = ""
    for i in f1.read ():
        code += i

Hope you understand what I did there. I opened a file called something.html, and returned everything in that file in the form of the code variable.
Now, let's create a template out of that file.

def showName (request):
    f1 = open ("/path/to/file/something.html")
    code = ""
    for i in f1.read ():
        code += i
    t = Template (code)

As I said earlier, I passed file contents in the form of a string to the Template method. We'll consider the same code we used for for and if in the last post (I'm hoping you will add all the other necessities to make it valid HTML code). Now let's pass data to {{ name }} using Context.

def showName (request):
    f1 = open ("/path/to/file/something.html")
    code = ""
    for i in f1.read ():
        code += i
    t = Template (code)
    c = Context ({'name':'tejas'})

As you can see, you have to pass a dictionary as a parameter to the Context method. The keys are the variables used in the templating language, and the values are the values we want them to have. The values can be variables too. But the keys have to be strings.
Finally, let's render the page.

def showName (request):
    f1 = open ("/path/to/file/something.html")
    code = ""
    for i in f1.read ():
        code += i
    t = Template (code)
    c = Context ({'name':'tejas'})
    html = t.render (c)
    return HttpReponse (html)

The second to last statement tells the system to render the context c to the template t. Assign this to a variable and return HttpResponse of this variable.
In the next part, we'll see how to render context with content from databases. Au revoir!

Django Templating Language - Part II

Now let's look at some in-built tags. These will help you arrange data efficiently on your page. These are a lot like XML. However, the syntax is different and it is easier to manage.
If you've noticed, it says Django Templating Language. Thus, as with every other language, this one also has control structures. Let's look at a few.
(Note: We're still learning the language, and even at the end of this post the code will print raw data. I swear, we're really close to rendering data from Python. Just hang tight for one more post.)

FOR:
This simulates a for loop. It is useful when extracting data from a database and rendering on the page, especially when you don't know the number of rows that will be returned. This will simply iterate over the list and render everything.

<html>
{% for row in rows %}
<b><i>{{ row }}</i></b><br>
{% endfor %}
</html>

Let's look at this code step by step. First of all, let's map the for here with that in Python.
In Python:
for i in lst
Thus, i is row, the variable that we will use to iterate over the list of rows that the database returns. lst is rows, the list over which we need to iterate. You can name them whatever you want. Iterating over the list is useless if you don't do anything with the data. As you can see, I've simply printed the value. (As row is a variable, it is enclosed within {{ }}).
Again, this is assuming that each row has only one field. This is seldom the case. We'll see how to render rows with multiple fields when we see Python rendering in general.

IF:
This will simulate an if block. Now, elif won't work in Django 1.3, but it does in 1.6 onwards. If you want an elif statement, just put it under else and then if.
We normally compare two values in if. So Django ships two tags, ifequal and ifnotequal.

<html>
{% ifequal name "tejas" %}
<b><i>{{ name }}</i></b><br>
{% endifequal %}
</html>

<html>
{% ifnotequal name "tejas" %}
<b><i>{{ name }}</i></b><br>
{% endifnotequal %}
</html>

ifequal compares name and "tejas" to see if they're equal. It's Python equivalent would be if name == "tejas". These are the two parameters. They may be variables, strings, or any hard coded values of any data type.

ifnotequal compares name and "tejas" to see if they're not equal. It's Python equivalent would be if name != "tejas".

Great! We've learned the basics of Django's Templating Language. As usual, you can comment or inbox me with your queries. In the next post we see how to actually put data there through Python (Yay!).
You didn't Yay did you? Come on guys, a little more enthusiasm!

Django 1.6

Hi all! Today let's explore Django's newest version. This won't be in incredible detail, however. The post would be too long. We'll just see an overview. Even as we speak the developers are working on versions 1.7 and 1.8

Let's start at the top.

Django 1.3 Django 1.6
Project directory structure The structure is the same as we explored earlier. Once you open the project directory, you can see the list of apps, __init__.py, manage.py, settings.py, and urls.py. The structure here is slightly different. Once you open the project directory, there is another folder with the same name as your project. The manage.py is here too. Inside the other directory are all the apps and settings etc. While this provides a certain level of independence and atomicity, I personally am disappointed with this. I liked the older one better, and the new one takes some getting used to.
Settings The settings file contains all settings imaginable, with the ability to add your own. The default settings file shipped with 1.6 is spartan and contains only those settings that an app absolutely needs to run. Rest all need to be added, e.g. TEMPLATE_DIRS, STATIC_DIRS etc.
WSGI (Web Server Gateway Interface) No additional wsgi file Shipped with a default wsgi file (wsgi.py) to configure the interface.
Database configuration The ENGINE field is supposed to hold the DBMS you use, like sqlite3, mysql etc. The ENGINE field now has to include the full specification, i.e. django.db.backends.sqlite3, django.db.backends.mysql etc.

These are the changes I noticed and those that directly affect my coding style in Django. Feel free to comment ones that you've noticed. Until next time.