Contents

Django: Building a basic site with Admin

Moving my site I realized that I have’t wrote any post about Django. I was sure enough to have been done it. So I must solve this problem XD

Django

What is that?

Django is a framework to build web applications. It is centered on the backend, offering you templates to use in the frontend, but it is possible that you need another additional framework for this layer, just like JQuery , Dojo , Mootools , Prototype , etc.

Installation

We can install it by using easyinstall , althought it has already a Debian package. You can isolate the Django installation, in order to clone it easily.

Creation

Let’s see how to build a little CMS. It is going to contain posts and nothing more. With this goal, the first step will be telling to Django about creating the site:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
$ django-admin startproject myblog
$ cd myblog
$ python manage.py startapp blog
$ tree
.
|-- blog
|   |-- __init__.py
|   |-- models.py
|   |-- tests.py
|   `-- views.py
|-- __init__.py
|-- manage.py
|-- settings.py
`-- urls.py

1 directory, 10 files
$

Before continuing on, let’s configure our database, modifying settings.py file, where we must write the database to use. By the way, we will update the installed applications to use “admin” and our new module.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'database.db',
        'USER': '',
        'PASSWORD': '',
        'HOST': '',
        'PORT': '',
    }
}

TEMPLATE_DIRS = (
    '/absolute_path/'
)

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.admin',
    'blog',
)

Leave everything else untouched.

Now we can run the server, but it is going to do very few things:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$ python manage.py syncdb
Creating tables ...
Creating table auth_permission
Creating table auth_group_permissions
Creating table auth_group
Creating table auth_user_user_permissions
Creating table auth_user_groups
Creating table auth_user
Creating table auth_message
Creating table django_content_type
Creating table django_session
Creating table django_site

You just installed Django's auth system, which means you don't have any superusers defined.
Would you like to create one now? (yes/no): yes
Username (Leave blank to use 'miguel'): admin
E-mail address: admin@example.com
Password:
Password (again):
Superuser created successfully.
Installing custom SQL ...
Installing indexes ...
No fixtures found.
$ python manage.py runserver
Validating models...

0 errors found
Django version 1.3, using settings 'myblog.settings'
Development server is running at https://127.0.0.1:8000/
Quit the server with CONTROL-C.

And we can open the site, that can be found at https://127.0.0.1:8000.

The model

Let’s edit the model (blog/models.py), and write a very basic model:

1
2
3
4
5
from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=200)
    body = models.TextField()

As you can see, we will have a title and a body. It is not necessary anything else right now.

URLs

Now we are going to update the file urls.py. This file is going to be used to allow django to decide what to do with each URL that is requested. That is the reason it works with regular expressions, allowing it to identify which service or HTML must process for each case. We need to uncomment django-admin lines (urls.py file):

1
2
3
4
5
6
7
8
from django.conf.urls.defaults import patterns, include, url
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    url(r'^admin/', include(admin.site.urls)),
    url(r'^blog/', 'myblog.blog.views.list'),
)

Administration

We are going to configure the administration tool, to allow us to edit our entries. We are going to use the file blog/admin.py

1
2
3
4
from myblog.blog.models import Post
from django.contrib import admin

admin.site.register(Post)

The View

In the URLs file we can write that, when the URL blog/ is found, we will see blog.views.list. It is not defined yet, and we will do it in file ‘admin/views.py:

1
2
3
4
5
6
from django.shortcuts import render_to_response
from blog.models import Post

def list(request):
    return render_to_response('blog/list.html',
                              {'post_list': Post.objects.all()})

With this step we have just made a dependency: blog/list.html. In this case, we will need to build a template. Templates are something away from our project, and they are isolated of it. When you build a Django site, modules are installed in a place, each of them installed as isolated as it can be possible from others. If it is possible, they must have no dependency with the others (if it is possible, I said). It will be templates which give our project the homogeneity and join all the site. We wrote a path for TEMPLATE_DIRS in the ‘settings.py’ file. You must create the file blog/list.html there:

We are using the variable post_list in our template, looping on it and rendering it how we want.

How to use it

Everything is done!! Hmmm… And what’s next?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<html>
<head>
  <title>Lista de Posts</title>
</head>
<body>
<h1>Lista de Posts</h1>{% if post_list %}
   <ul>
     {% for post in post_list %}
     <li>{{ post.title }}</li>
     {% endfor %}
   </ul>{% else %}
   <p>No blogs found.</p>{% endif %}
</body>
</html>

Well, we are going to use it. First of all, let’s assure our database is updated and let’s run the server:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
$ python manage.py syncdb
Creating tables ...
Installing custom SQL ...
Installing indexes ...
No fixtures found.
$ python manage.py runserver
Validating models...

0 errors found
Django version 1.3, using settings 'myblog.settings'
Development server is running at https://127.0.0.1:8000/
Quit the server with CONTROL-C.

Now everything is working. We can open the URL that the message was saying to us: https://127.0.0.1:8000 , what carries us to a wonderful “page not found” error. As far as we have debugging option enabled, we can read what happened: The requested URL does not match any defined patterns.

Let’s try the admin interface: https://127.0.0.1:8000/admin . It will ask us the password (that we choose when we did first “syncdb”) and we enter as administrators. We should see three blocks:

  • Auth
  • Blog
  • Sites

If you can see them it is because you did everything right. Create a couple of posts in the “Blog” module. It is not difficult enough.

All these stuff related to the admin interface has been created automatically by using “django-admin” module.

Do you have 2-3 posts? All right. Let’s see the view: https://127.0.0.1:8000/blog . There is nothing to say here but we must be seeing our blog :D

More information

As you can imagine, the wonderful django tutorial :D.

Goodbyes

If I see this issues are interesting, maybe some day I will continue with this little manual. There are a lot of things to be done now:

  • To paginate entries if there are a lot
  • To create a CRUD interface to avoid to edit posts from admin interface
  • To give some color to the site.
  • Add tags to our posts.
  • Sort them by publishing date.
  • Manage users
  • Add some tests
  • [Think whatever you want and write it here]