Posts Tagged ‘django’

Simple example of Django on shared host

October 12th, 2009
2
Digg me

Displayofpatience.net runs on a shared host. It’s basically your avarage wordpress site, and the whole domain is dedicated to it. In addition to wordpress, I wanted to try if I could run a django site along with it. The first thing was to install Django.

Running stuff on a shared host can be tricky. Installing stuff can be even trickier. My first task was to install Django. Even though my host/webhotel provided Django, I wanted to use a newer version. After digging around I found a wonderful little script for creating a virtual environemnt for Python. It basically creates bin & lib (& site-packages) directories to your home directory and links them to the system-wide python. Only now when you use your “local” python you can safely install stuff to the site-packages directory, using basic “setup.py install” method. It works great and you need no additional priviledges as you install everything under your home directory. Pretty cool. Check out more information about virtual-python here.

After installing Django I was ready to try to set up a live site using it. I didn’t have any real needs for my Django site, so I decided to just hack something up, that demonstrates that I can use Django on my shared host. Displayofpatience.net runs on Apache, so I figured fcgi was the way to go. I created a .fcgi script according Django documentation and it worked out of the box. I, of course, used my own “local” python for running the fcgi script. Then I just configured  .htaccess file to handle .fcgi files (all in the Django docs). Django takes care from that on, according to the project urls.py.

Here is the outcome: The awesome Lottery machine!

To spice things up a little, I also added some JQuery ajax and animations to my program.  I hadn’t tried JQuery before, so that too was also a nice learning experience. I’m really happy about the outcome. Of course, the actual program is pretty useless, but now I can run my wordpress site as usually and Django applications along with it.

Django 1.0 Website Development by Ayman Hourieh -preview

April 21st, 2009
6
Digg me

The following is an extract from the recently published book Django 1.0 Website Development” by Ayman Hourieh. I haven’t read it yet, but I’ll be writing a review as soon as I get my hands on it. The example covers basics of developing Django applications, and it should be a nice read for those unfamiliar with Django. I think it also gives you a good idea what the whole book is going to be like.  Anyway, the following is a (slightly formatted) copy/paste from the Packt Publishing website. There are also few other extracts available there. 

Building Friend Networks with Django 1.0

Running a social web application means having a community of users who have common interests, and who use the application to share their interests and findings with each other. We will want to enhance the social experience of our users.

An important aspect of socializing in our application is letting users to maintain their friend lists and browse through the bookmarks of their friends. So, in this section we will build a data model to maintain user relationships, and then program two views to enable users to manage their friends and browse their friends’ bookmarks.

Creating the friendship data model

Let’s start with the data model for the friends feature. When a user adds another user as a friend, we need to maintain both users in one object. Therefore, the Friendship data model will consist of two references to the User objects involved in the friendship. Create this model by opening the bookmarks/models.py file and inserting the following code in it:

class Friendship(models.Model):
  from_friend = models.ForeignKey(User, related_name='friend_set')
  to_friend = models.ForeignKey(User, related_name='to_friend_set')
 
  def __unicode__(self):
    return u'%s, %s' % (self.from_friend.username, self.to_friend.username)
 
  class Meta:
    unique_together = (('to_friend', 'from_friend'), )

The Friendship data model starts with defining two fields that are User objects: from_friend and to_friend. from_friend is the user who added to_friend as a friend. As you can see, we passed a keyword argument called related_name to both the fields. The reason for this is that both fields are foreign keys that refer back to the User data model. This will cause Django to try to create two attributes called friendship_set in each User object, which would result in a name conflict. To avoid this problem, we provide a specific name for each attribute. Consequently, each User object will contain two new attributes: user.friend_set, which contains the friends of this user and user.to_friend_set, which contains the users who added this user as a friend. Throughout this article, we will only use the friend_set attribute, but the other one is there in case you need it .

Next, we defined a __unicode__ method in our data model. This method is useful for debugging.

Finally, we defined a class called Meta. This class may be used to specify various options related to the data model. Some of the commonly used options are:

  • db_table: This is the name of the table to use for the model. This is useful when the table name generated by Django is a reserved keyword in SQL, or when you want to avoid conflicts if a table with the same name already exists in the database.
  • ordering: This is a list of field names. It declares how objects are ordered when retrieving a list of objects. A column name may be preceded by a minus sign to change the sorting order from ascending to descending.
  • permissions: This lets you declare custom permissions for the data model in addition to add, change, and delete permissions. Permissions should be a list of two-tuples, where each two-tuple should consist of a permission codename and a human-readable name for that permission. For example, you can define a new permission for listing friend bookmarks by using the following Meta class:
    class Meta:
      permissions = (('can_list_friend_bookmarks', 'Can list friend bookmarks'),)
  • unique_together: A list of field names that must be unique together.

We used the unique_together option here to ensure that a Friendship object is added only once for a particular relationship. There cannot be two Friendship objects with equal to_friend and from_friend fields. This is equivalent to the following SQL declaration:

UNIQUE ("from_friend", "to_friend")

If you check the SQL generated by Django for this model, you will find something similar to this in the code.

After entering the data model code into the bookmarks/models.py file, run the following command to create its corresponding table in the database:

$ python manage.py syncdb

Now let’s experiment with the new model and see how to store and retrieve relations of friendship. Run the interactive console using the following command:

$ python manage.py shell

Next, retrieve some User objects and build relationships between them (but make sure that you have at least three users in the database):

>>> from bookmarks.models import *
>>> from django.contrib.auth.models import User
>>> user1 = User.objects.get(id=1)
>>> user2 = User.objects.get(id=2)
>>> user3 = User.objects.get(id=3)
>>> friendship1 = Friendship(from_friend=user1, to_friend=user2)
>>> friendship1.save()
>>> friendship2 = Friendship(from_friend=user1, to_friend=user3)
>>> friendship2.save()

Now, user2 and user3 are both friends of user1. To retrieve the list of Friendship objects associated with user1, use:

>>> user1.friend_set.all()
[<Friendship: user1, user2>, <Friendship: user1, user3>]

(The actual usernames in output were replaced with user1, user2, and user3 for clarity.)

As you may have already noticed, the attribute is named friend_set because we called it so using the related_name option when we created the Friendship model.

Next, let’s see one way to retrieve the User objects of user1′s friends:

>>> [friendship.to_friend for friendship in 
user1.friend_set.all()]
[<User: user2>, <User: user3>]

The last line of code uses a Python feature called “list” comprehension to build the list of User objects. This feature allows us to build a list by iterating through another list. Here, we built the User list by iterating over a list of Friendship objects. If this syntax looks unfamiliar, please refer to the List Comprehension section in the Python tutorial.

Notice that user1 has user2 as a friend, but the opposite is not true.

>>> user2.friend_set.all()
[]

In other words, the Friendship model works only in one direction. To add user1 as a friend of user2, we need to construct another Friendship object.

>>> friendship3 = Friendship(from_friend=user2, to_friend=user1)
>>> friendship3.save()
>>> user2.friend_set.all()
[<Friendship: user2, user1>]

By reversing the arguments passed to the Friendship constructor, we built a relationship in the other way. Now user1 is a friend of user2 and vice-versa. Experiment more with the model to make sure that you understand how it works. Once you feel comfortable with it, move to the next section, where we will write views to utilize the data model. Things will only get more exciting from now on!

Writing views to manage friends

Now that we are able to store and retrieve user relationships, it’s time to create views for these features. In this section we will build two views: one for adding a friend, and another for listing friends and their bookmarks.

We will use the following URL scheme for friend-related views:

  • If the view is for managing friends (adding a friend, removing a friend, and so on), its URL should start with /friend/. For example, the URL of the view that adds a friend will be /friend/add/.
  • If the view is for viewing friends and their bookmarks, its URL should start with /friends/. For example, /friends/username/ will be used to display the friends of username.

This convention is necessary to avoid conflicts. If we use the prefix /friend/ for all views, what happens if a user registers the username add? The Friends page for this user will be /friend/add/, just like the view to add a friend. The first URL mapping in the URL table will always be used, and the second will become inaccessible, which is obviously a bug.

Now that we have a URL scheme in mind, let’s start with writing the friends list view.

The friends list view

This view will receive a username in the URL, and will display this user’s friends and their bookmarks. To create the view, open the bookmarks/views.py file and add the following code to it:

def friends_page(request, username):
  user = get_object_or_404(User, username=username)
  friends = [friendship.to_friend for friendship in user.friend_set.all()]
  friend_bookmarks = Bookmark.objects.filter(user__in=friends).order_by('-id')
  variables = RequestContext(request, {
    'username': username,
    'friends': friends,
    'bookmarks': friend_bookmarks[:10],
    'show_tags': True,
    'show_user': True})
  return render_to_response('friends_page.html', variables)

This view is pretty simple. It receives a username and operates upon it as follows:

  • The User object that corresponds to the username is retrieved using the shortcut method get_object_or_404.
  • The friends of this user are retrieved using the list comprehension syntax mentioned in the previous section.
  • After that, the bookmarks of the user’s friends are retrieved using the filter method. The user_in keyword argument is passed to filter in order to retrieve all the bookmarks of the user who exists in the friends list. order_by is chained to filter for the purpose of sorting bookmarks by id in a descending order.
  • Finally, the variables are put into a RequestContext object and are sent to a template named friends_page.html. We used the index syntax with friend_bookmarks to get only the latest ten bookmarks.

Let’s write the view’s template next. Create a file called friends_page.html in the templates folder with the following code in it:

{% extends "base.html" %}

{% block title %}Friends for {{ username }}{% endblock %}
{% block head %}Friends for {{ username }}{% endblock %}

{% block content %}
 <h2>Friend List</h2>
 {% if friends %}
 <ul class="friends">
 {% for friend in friends %}
 <li><a href="/user/{{ friend.username }}/">
 {{ friend.username }}</a></li>
 {% endfor %}
 </ul>
 {% else %}
 <p>No friends found.</p>
 {% endif %}

 <h2>Latest Friend Bookmarks</h2>
 {% include "bookmark_list.html" %}
{% endblock %}

The template should be self-explanatory; there is nothing new in it. We iterate over the friends list and create a link for each friend. Next, we create a list of friend bookmarks by including the bookmark_list.html template.

Finally, we will add a URL entry for the view. Open the urls.py file and insert the following mapping into the urlpatterns list:

urlpatterns = patterns('',
 [...]
 # Friends
(r'^friends/(w+)/$', friends_page), )

This URL entry captures the username portion in the URL using a regular expression, exactly the way we did in the user_page view.

Although we haven’t created a view for adding friends yet, you can still see this view by manually adding some friends to your account (if you haven’t done so already). Use the interactive console to make sure that your account has friends, and then start the development server and point your browser to http://127.0.0.1:8000/ friends/your_username/ (replacing your_username with your actual username). The resulting page will look something similar to the following screenshot:

djangoweb-article2-image01

So, we now have a functional Friends page. It displays a list of friends along with their latest bookmarks. In the next section, we are going to create a view that allows users to add friends to this page.

Creating the add friend view

So far, we have been adding friends using the interactive console. The next step in building the friends feature is offering a way to add friends from within our web application.

The friend_add view works like this: It receives the username of the friend in GET, and creates a Friendship object accordingly. Open the bookmarks/views.py file and add the following view:

@login_required
def friend_add(request):
  if 'username' in request.GET:
    friend = get_object_or_404(User, username=request.GET['username'])
    friendship = Friendship(from_friend=request.user,to_friend=friend)
    friendship.save()
    return HttpResponseRedirect('/friends/%s/' % request.user.username)
  else:
    raise Http404

Let’s go through the view line by line:

  • We apply the login_required decorator to the view. Anonymous users must log in before they can add friends.
  • We check whether a GET variable called username exists. If it does, we continue with creating a relationship. Otherwise, we raise a 404 page not found error.
  • We retrieve the user to be added as a friend using get_object_or_404.
  • We create a Friendship object with the currently logged-in user as the from_friend argument, and the requested username as the to_friend argument.
  • Finally, we redirect the user to their Friends page.

After creating the view, we will add a URL entry for it. Open the urls.py file and add the highlighted line to it:

urlpatterns = patterns('',
 [...]
 # Friends
 (r'^friends/(w+)/$', friends_page),
 (r'^friend/add/$', friend_add),
)

The “add friend” view is now functional. However, there are no links to use it anywhere in our application, so let’s add these links. We will modify the user_page view to display a link for adding the current user as a friend, and a link for viewing the user’s friends. Of course, we will need to handle special cases; you don’t want an “add friend” link when you are viewing your own page, or when you are viewing the page of one of your friends.

Adding these links will be done in the user_page.html template. But before doing so, we need to pass a Boolean flag from the user_page view to the template indicating whether the owner of the user page is a friend of the currently logged-in user or not. So open the bookmarks/views.py file and add the highlighted lines into the user_page view:

def user_page(request, username):
  user = get_object_or_404(User, username=username)
  query_set = user.bookmark_set.order_by('-id')
  paginator = Paginator(query_set, ITEMS_PER_PAGE)
  if request.user.is_authenticated():
    is_friend = Friendship.objects.filter(from_friend=request.user, to_friend=user)
  else:
    is_friend = False
  try:
    page_number = int(request.GET['page'])
  except (KeyError, ValueError):
    page_number = 1
  try:
    page = paginator.page(page_number)
  except InvalidPage:
    raise Http404
  bookmarks = page.object_list
  variables = RequestContext(request, {
    'username': username,
    'bookmarks': bookmarks,
    'show_tags': True,
    'show_edit': username == request.user.username,
    'show_paginator': paginator.num_pages &gt; 1,
    'has_prev': page.has_previous(),
    'has_next': page.has_next(),
    'page': page_number,
    'pages': paginator.num_pages,
    'next_page': page_number + 1,
    'prev_page': page_number - 1,
    'is_friend': is_friend,})
  return render_to_response('user_page.html', variables)

Next, open the templates/user_page.html file and add the following highlighted lines to it:

[...]
{% block content %}
 {% ifequal user.username username %}
<a href="/friends/{{ username }}/">view your friends</a>
{% else %}
{% if is_friend %}
<a href="/friends/{{ user.username }}/">
{{ username }} is a friend of yours</a>
{% else %}
<a href="/friend/add/?username={{ username }}">
add {{ username }} to your friends</a>
{% endif %}
- <a href="/friends/{{ username }}/">
view {{username }}'s friends</a>
{% endifequal %} {% include "bookmark_list.html" %} {% endblock %}

Let’s go through each conditional branch in the highlighted code:

  1. We check whether the user is viewing his or her page. This is done using a template tag called ifequal, which takes two variables to compare for equality. If the user is indeed viewing his or her page, we simply display a link to it.
  2. We check whether the user is viewing the page of one of their friends. If this is the case, we display a link to the current user’s Friends page instead of an “add friend” link. Otherwise, we construct an “add friend” link by passing the username as a GET variable.
  3. We display a link to the Friends page of the user page’s owner being viewed.

And that’s it. Browse some user pages to see how the links at the top change, depending on your relationship with the owner of the user page. Try to add new friends to see your Friends page grow.

Implementing the friends feature wasn’t that hard, was it? You wrote one data model and two views, and the feature became functional. Interestingly, the more Django experience you gain, the more easy and fast its implementation becomes.

Our users are now able to add each other as friends and monitor their friends’ bookmarks.

Summary

In this article we developed an important feature for our project. Friend networks are very important in helping users to socialize and share interests together. These features are common in Web 2.0 applications, and now you are able to incorporate them into any Django web site.

 


If you have read this article you may be interested to view :

 

 

 


 

 

About the Author

Ayman Hourieh holds a bachelor degree in Computer Science. He joined the engineering team at Google in January 2008. Prior to that, he worked with web application development for more than two years. In addition, he has been contributing to several open source projects such as Mozilla Firefox. Ayman also worked as a teaching assistant in Computer Science courses for one year. Even after working with a variety of technologies, Python remains Ayman’s favorite programming language. He found Django to be a powerful and flexible Python framework that helps developers to produce high-quality web applications in a short time.

Test-driving Django-application development

February 8th, 2009
3
Digg me

Test-Driven Development (TDD) is something that I’m currently really excited about. It’s nothing new in the world of software development, but it’s very new to me. I have read lots about it but I haven’t been able to start experiencing with it at work for various reasons (excuses!). Anyway, finally I decided to start a personal project of my own, where I would begin to start learning TDD in practice. I chose to re-create a webstore-application I had previously written in PHP many years ago. I guess it would’ve been easier to start with something else than web-development but I’ve been playing around with a webframework called Django, which is excellent, and I figured I should combine those two. For a second I thought about using some PHP framework like Zend, but I just prefer Python.

I started by googling, if someone had used TDD while developing Django-applications. There was not much to be found, and for the most part it was outdated. However, I found some interesting blog posts about testing in general with django. I especially found small django tips from one newbie to another by Adam Smith very useful. I had worked with Django before and I knew the basics of TDD so low search results didn’t matter much. I was ready to begin.

The first thing I did was to set-up the development environment. I created the Django-project and the app inside it. I guess there are many ways you could Test-Drive in this situation but I wanted to use Django’s way of testing. So basically this means that I need to run the tests by executing “manage.py test” within my project. This will sniff the insides of django-applications for tests.py file (and models.py with tests inside that). The result of the command is the same you get from standard Python unittests runs. Of course you can specify the app with the command, but in the beginning there is just one app to begin with, so it was ok to run all tests. Everything so far, was created by Django, including example tests.py file within the application. You can use Python Unittest or Docstring frameworks. I chose Unittest, since I’m more familiar with the xUnit frameworks such as JUnit. I think there was a mention in the Django docs, that you can also use other test tools.

I experimented a little with the Python interactive interpreter on how the tests work. At this time I started to think that having just one tests.py is going get crowded pretty soon so I created a module my_tests under the application and created model_tests.py and view_tests.py under it. I figured I wanted to keep the views as compact as possible and write the logic to either to the model classes or somewhere else, which would be decided later. For now, model and view tests should be enough to get me started. I also wanted to separate my test files from the actual code. Here is a sketch of my project configuration:

Django-project/
--settings.py
--/my_webstore_application/
----views.py
----models.py
----tests.py
------/my_tests/
--------model_tests.py
--------view_tests.py
--------test_utils.py

The tests.py is just a collection of suites:

import unittest
import my_tests.view_tests
import my_tests.model_tests
 
def suite():
    suite1 = unittest.TestLoader().loadTestsFromModule(my_tests.view_tests)
    suite2 = unittest.TestLoader().loadTestsFromModule(my_tests.model_tests)
    alltests = unittest.TestSuite([suite1, suite2])
    return alltests

I also created a run-configuration for Eclipse, so the RED-GREEN-REFACTOR –cycle would be as fluent as possible. Here are some of the first tests I wrote (These are actually somewhat refactored, but the basic idea has remained):

*model_tests.py

from django.test import TestCase
from django.core.files.images import ImageFile  
from webstore.models import Product, Category, SubCategory, Image
from utils import *
 
 
class ProductTest(TestCase):
    def test_create_product(self):
        product = Product(name='test product 1', price="15.50", 
                          description='What a great product!')
        self.assertEquals(product.name, str(product))
 
class CategoryTest(TestCase):
    def test_create_category(self):
        category = Category(name='test category 1')
        self.assertEquals(category.name, str(category))

*view_tests.py

from django.test.client import Client
from django.test import TestCase
from utils import *
from merinostore.webstore.models import *
 
class ProductTest(TestCase):
    def setUp(self):
        self.client = Client()
        self.category = Category(name='test category 1')
        self.category.save()
        self.subcategory = SubCategory(name='test subcategory 2')
        self.subcategory.save()
        self.product = Product(name='test product 1', price='15.50', 
                               description='What a great product!',
                               category=self.category, subcategory=self.subcategory)
        self.product.save() 
 
    def test_list_products_template(self):
        response = self.client.get('/products/')
        self.failUnlessEqual(response.status_code, 200)
        self.assertTemplateUsed(response, 'product/list_products.html')
 
    def test_list_products(self):
        create_products(self.category, amount=10)
        response = self.client.get('/products/')
        self.failUnlessEqual(len(response.context[1]['products']), 11)

So I started with the models. I soon figured out that at this point there is virtually no code created by me in models so I stopped doing those and concentrated on the view tests. If the models are broken, they cannot be used anywhere. Later I started to write some more model tests, as I defined my own functions for them. As you can see, I use the Django helpers such as Client, which can be used to emulate the browser. I also use Django’s own TestCase class for assertions.

I was a little bit concerned about testing through views. This means I deal with real instances of the models, which exist in the database. It isn’t unit testing anymore if the tests hit the database, right? Luckily, Django’s test system is pretty good by default. It creates in-memory sqlite database for testing and you can even use fixtures with that. I just couldn’t find any reason for doing any heavier separation between the code and the database as running the tests were fast enough for me. Webstore application itself is mostly just about displaying items from the database. Of course, with the order handling and such tasks, I still plan to keep the logic separated from the views as much as possible. I figured as long as I write tests in order to drive design, it’s good.

I’m still in the process of developing the application, I have just finished the first feature, which is displaying of product list by categories (I copied the html stuff from the old store). What I didn’t do is test drive the templates. It just feels too much work, but I guess I could try that one as well.

I’m quite happy about the whole process in generally. At first I felt that I was proceeding very slowly, but at the same time it felt surprisingly good to get the GREEN showing up. I also created a simple script to import the data (products for now) from my previous webstore implementation, and I didn’t use TDD for that. The reason I didn’t Test-Drive is because I felt the script is so small and will be used only once so I wanted just to be done with it. It turned out to be hideous, and now I feel bad I didn’t TDD it (I think I’m going to rewrite that as well for practice). So I guess I’m learning something!

I’ll post more on the subject as I proceed or get the application ready. I’m sure that my tests aren’t very good and I’m doing many things wrong, but in order to better myself I hope I get some feedback. Till next time!