Sunday, August 30, 2015

How to make one view do the work of two

Hey folks! Today's is an interesting topic: making one view do two functions. In fact, you can make it do more than two; you an make them do 8 at a time. Think of it as view overloading, if you're into that kind of thing.
So let's dive into it.

Take logging into your account for example. Initially what I used to do is split this process into three views: one for displaying the login page, one for verification of credentials, and a third for displaying the profile. With the new method I will outline in this post you can do that using only two views rather than three. We'll combine displaying the login page and credential verification into one view. The way well do that will use HTTP request methods. Let's see what those are (going to take a little help from TutorialsPoint for the exact definitions):

  1. GET: This method is used to extract data that is embedded in the URL. The data is identified by a '?'. For example, in the URL "http://some.url/?data1=value1&data2=value2" the data after the '?' can be translated as {'data1':'value1', 'data2':'value2'}
  2. HEAD: This one is the same as GET, but this one only transfers status line and header section
  3. POST: This method sends data directly to the server rather than embedding it in the URL. It is used for handling sensitive data like passwords and credit card numbers. That way, when a user enters it in the browser, it cannot be seen by someone standing behind him
  4. PUT: This is an upload based method. The representations of target resource are replaced with uploaded content
  5. DELETE: As the name indicates, this method deletes all representations of the target resource
  6. CONNECT: Establishes a connection with the server
  7. OPTIONS: Describes communication options for target resource
  8. TRACE: Performs a loopback test on connection tunnel
Now each webpage can be accessed using one of those methods. you can overload a view by using an if  block to see what access method is used and do a different thing based on that.

def login(request):
    if request.method == "GET":
        return render(request, "login.html")
    elif request.method == "POST":
        # code to authenticate user

As you can see, in this case, if the request method is GET, which it is by default, it'll just render the login page. Normally, in the login form the action will be POST since we'll be asking for passwords. So the first page will be rendered due to the GET method and the verification will be done by the POST method. So this way you can overload views.
That's all for today folks!

Thursday, July 16, 2015

How to access your Django site from a different computer

Hey guys! Today we'll see how to access your Django site from another computer. Now this won't be a problem if you've hosted on a remote server like PythonAnywhere or Heroku. But what if you have hosted it on your local machine and want to provide people with access to it?

I'm developing an online mentorship platform for my college that is hosted on the college server. So for that I had to use this concept. Before you do this, however, here's a disclaimer: only computers connected in the same network as your local machine can access your Django site. You can, of course, provide global access, but there's a lot of complicated networking stuff involved in that. Let's not go into that right now.

So let's get on with it. You know the command for hosting and accessing the site on your local machine is python manage.py runserver. This essentially gives your local machine server capabilities and lets you access it from the same machine. However, to let other machines access it, here's the command:
python manage.py runserver <ip_address>:<port_number>

Replace <ip_address> with your machine's IP address. If you don't know the IP address, do one of the following:
  • Windows: Open command prompt and type ipconfig. There'll be a field that reads IPv4 Address. That's the address you should put in your runserver command.
  • Linux/Mac: Open terminal and type ifconfig. There'll be a field that reads inet address. Now there might be two fields that read that. If you're connected by Ethernet, use the one listed under Ethernet. If you're connected by Wi-Fi, use the one listed under WLAN0
As for the <port_number>, the default port for any Django project is 8000. However, you can use any port you want with the exceptions of the ones used for say SMTP and Telnet.

Let's look at an example. If my IP address is 172.20.55.21 and I want to use the standard port, i.e. 8000, my command will look like this:
python manage.py runserver 172.20.55.21:8000

Then, any user wanting to access it, (again, from the same network, can't stress that enough) should simply type 172.20.55.21:8000 in the URL bar and he will be able to view and use the site.

Tuesday, June 9, 2015

Deploying a Django application - Part I

Well, first and foremost, this blog just crossed 1000 page views. Sincere thanks to all readers. Despite what the title indicates, this is not the last post. The world of Django is ever changing and there's always new stuff to learn. But this post (or series of posts, haven't decided yet) will show you how to deploy the project you've created to a server and make it battle ready.

I was recently drafted by my college to create and deploy an online mentorship platform. We have a mentorship process that involves scheduling meetings with mentors and discussing attendance, marks and also stuff like grievances. The college wants to make it paper free. So here I am. It's a point of pride, because I'm creating and deploying all by myself.

Anyway, first off, let's see what all we need to pull this off. Here's the list:

  1. Working Django code (duh.)
  2. A dedicated computer that will act as a server. Specifications:
    • At least 4 GB RAM (to handle multiple concurrent requests)
    • At least 500 GB Hard Disk space (to store the database and static files)
    • Django installation: same as or one compatible with the one you developed your project in
    • A static IP address that is unique within the network you want to host the service in
    • Side note: You might want to consider multiple servers if you anticipate thousands of requests per hour. Otherwise just one is OK
Have you got all this? Great! Now let's see what changes you need to make in the code to make it deployment ready. Here are a few things off the top of my head. They're pretty basic. We'll go into more details in subsequent posts. I guess I've made up my mind now :P Anyway, here they are:

  1. Change DEBUG = True to DEBUG = False in the settings file. The reason for this is that if there's an error Django gives you the comprehensive report, along with some part of the code. You don't want the users to be able to see that
  2. If you need to have that, you can make two settings files: one for development and one for production. Here's how:
    • You can have two copies of the same file, with DEBUG True in one (development) and False in the other (production)
    • Alternatively, you can have a settings_production file that will import the main settings file. That way, all the user will see is an import statement in case of an error
    • Note that all this configuration and switching between two settings files have to be registered in the manage.py file before running the application
This is the initial preparation you need to make. I'm discontinuing here so that the post will be of appropriate size and not tedious to read. Keep checking!

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.

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!