Monday, January 5, 2015

Django Forms

This is another example of Django's reusability. We saw how to create your own form in HTML and render it and get data from it using GET or POST methods. Again, Django does this for you. While it certainly is useful knowing how to do this on a basic level, using Django's Forms API can give you more powerful forms with richer features.

Like models.py, create a file called forms.py in the app where the form is required. Let's create a simple contact form. In forms.py:

forms.py
from django import forms

class SimpleUploadForm (forms.Form):
    name = forms.CharField (label = "Enter name")
    email = forms.EmailField (
label = "Enter email ID", required = False)
    dob = forms.DateTimeField (
label = "Enter date of birth")

As you can see, just like a model, we created a simple form. Now let's render it from a view.

views.py
from django.shortcuts import render
from forms import SimpleContactForm

def simple_contact_form (request):
        form = SimpleContactForm ()
        return render (request, "simple_contact_form.html", {"form":form})


Here, we import the SimpleContactForm class from forms.py and initialize its instance in the view. Then we pass that instance as a context to the webpage we're rendering. The view will become clearer when you see the template.

simple_contact_form.html
<html>
        <head><title>Simple Contact Form</title></head>
       
        <body>
                <form action = "" method = "POST">

                        <table>
                                {{ form.as_table }}

                        </table>
                        {% csrf_token %}
                        <input type = "submit" value = "Submit">
                </form>
        </body>
</html>


Ok now let's break this down. First, form action = "" means the page doesn't change when the button is clicked. Now, in the form, we've passed the SimpleContactForm () instance as form to the template. That will be rendered in the <form> tag. The as_table method displays the form as a table. However, that only contains <tr>, <th> and <td> tags. So we have to add the <table> and </table> tags ourselves. Another form display method is as_p.

The {% csrf_token %} protects POST from, well, CSRF. If you remember I told you to comment that line which included that middleware class. You can uncomment it now and proceed normally.
See you around!

Saturday, January 3, 2015

HTTP headers

Many times you many need the IP address of the computer that's accessing your webapp. You may want it for a survey, or cataloging that user to offer better services and what not. Today we'll see not only how to get the IP address, but a host of other client side information that can be used to fine tune your app.

Let's take the IP address for example. I once needed it to see from where the app was being accessed from the most. I wrote a tracker that would piggyback on the client's signal and work backwards all the way to the source and get me the IP address. But little did I know that Django already does that for me. The IP address and host name (ISP) is encoded in the request parameter. Let's see how to view them.

To do this we'll create a simple view. In HTML, we'll create a list that contains header name and value, and then populate it through Django.

headers.html
<html>
        <head><title>Django HTTP headers</title></head>
        <body>
                <ul>
                        {% for header in headers %}
                                <li><b>{{ header.name }}</b>: {{ header.value }}</li>
                        {% endfor %}
                </ul>
        </body>
</html>

Pretty straightforward. Now let's populate the list.

views.py
from django.shortcuts import render

class Header (object):
        def __init__ (self, name, value):
                self.name, self.value = name, value

def headers (request):
        headers = []
        headers_list = request.META.items ()
        for name, value in headers_list:
                headers.append (Header (name, value))
        return render (request, "headers.html", {"headers":headers})


Let's see what's going on here. First, we import the render function. Then, we create a class called Header for use in the templating language. We already saw this with Student in Django Templating Language - Part IV. Now, request.META contains a list of headers and its method items() returns a list of tuples with name and value. We use that to populate the list in HTML.

One more thing. Notice how I provided the context directly as a parameter in the render function call? You can do that too. There's no need to do the Template/Context schedule each time.

App specific URLs

As you may know, Django boasts reusability of apps. This means you can just copy one app from one project, plug it into another and it would still work the same way. Neat, huh? Well, admittedly, till now we've only focused on getting out projects to run. But now that we know the basics of creating a working Django project, it's time to delve deeper and take advantage of Django's rich features.

Let's start with URLs. Till now, we just went on adding URLs to the main urls.py as we developed the project. But when the number of URLs starts going into the triple digits, the urls.py file can become massive and difficult to keep track of. So let's see how to create a urls.py file in each app and direct the main file to this new one.

In the main urls.py file, add a pattern that will point to the app:

url (r'^myapp/', include('myproject.myapp.urls')),

This tells Django that whenever someone access the /myapp/ URL they should be directed to the urls.py file in that app. From here on in, all the views rendered in this app will have URLs like /myapp/foo/bar. This makes them easier to manage. There's also another advantage: you no longer need unique URLs; you can have /home/ in multiple apps. That is, /myapp1/home and /myapp2/home have the same sub URL, but are still unique as a whole.

Now, create a urls.py in the concerned app. In it:

from django.conf.urls.defaults import *
(This imports all patterns from the original urls.py file)

urlpatterns = patterns ('myproject.myapp.views',

    url(r'^foo/', 'bar'),
)

Another advantage: you don't have to type the entire path to the view; just the name suffices. Hence, from the above example, when someone accesses the /myapp/foo/ URL, the bar view from myproject.myapp.views will be rendered.

To summarize, this makes handling URLs very easy. We'll see more examples of reusability in the following tutorials.