Django KFIMember Tutorial Part III - Configure Inital PostgreSQL Database Locally and Remotely in Openshift

Configuring PostgreSQL on Openshift

Configuring PostgreSQL on Openshift

ARTICLE UPDATE : As I have unresolved problem when using Python 3.3 combined with Django 1.6 and PostgrerSQL 9.2 in Openshift, I dropped Python 3.3 requirement and rework this application using Python 2.7 instead.

In Part II of this article we have already have an initial working application using Django and also import it into PTVS project. That's a good start. But the application still lack a fundamental requirement for any web database application : database support. In this article we are going to configure the initial Django database and improve it even further by using database migration feature using South. One important note about this article though, it first focused itself for Windows user.  Afterward, we are going to have a look on how it's done for *nix user, especially Ubuntu.

 

Configuring Local PostgreSQL for Windows

Install PostgreSQL

If you haven't downloaded PostgreSQL, please go to this download page and pick the 9.2.6 version. You may choose to download the 32/64 version. We pick the 9.2.x version, as it's the version currently being supported by Openshift. Install it, skipping the Stack Builder installation offering and finally launch Pg Admin III to create your initial database. You can name the database anything, but here, I am going to name it kfimember. Please note that, during PostgreSQL installation you were instructed to choose your password for postgres user (which is PostgreSQL default user), please remember it as it will be use in the later step of this application configuration process. And you don't have to be very secretive for this password, as it will be use for local database test only. Eventually you will use a much more secretive password coming from your Openshift PostgreSQL database.

Configure Psycopg2 Driver

Our Python Django application will eventually need to talk to PostgreSQL server lies in the background. For this to occur, every  Python application need a PostgreSQL driver. There are several PostgreSQL driver for Python actually, but the most popular driver is Pyscopg2. The easiest way to install Psycopg2 for Windows would be to download it from this page. Choose the one that match your Python version and follow its installer installation step. Afterward, you will have a valid and working PostgreSQL driver for Python.

Initialize Database

Maybe you were wondering, "Why is it with Django and database? Should web application can be developed without a proper database lies behind it?". That's true. But if it is, that is, you don't use database for your Django web application, well, then maybe it's not a proper way to use Django for your web application in the first place. Django framework is about how to develop a dynamic database driven web application within the shortest time effort and the greatest way possible. Or by using Django own tagline : The Web framework for perfectionists with deadlines.

Configure Django for Local PostgreSQL Connection

Now that we already have PostgreSQL installed in our local environment, complete with its Python driver using Psycopg2, we can continue our next step by configuring Django to use this new local database configuration. Open the file setting.py located in kfimember\wsgi\kfimember\kfimember\settings.py. This is a single Python file with sole purpose to configure all aspect of our Django application. You'll get in touch with this file intensively in the first time configuring your Django application. 

Find the line DATABASE = { ... } and modify it to match your local PostgreSQL database as follows:

1
2
3
4
5
6
7
8
9
10
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2', 
            'NAME': 'kfimember',
            'USER' : 'postgres',
            'PASSWORD' : 'change_with_your_local_postgresql_password',
            'HOST' : 'localhost',
            'PORT' : ''
        }
    }

Modify it to match your configuration, which in this case you only to have to modify the PASSWORD field. 

Introducing Django Default Applications

At this point of your application, you can test to run the application. If your database setting works, it will display the same default homepage view. So, you may not notice any different here. But, if you failed to configure your database, Django will display erroneous message to pinpoint that you haven't configure your database setting correctly. Try to pass this step first!

If you have successfully configure you PostgreSQL database configuration in Django, your next step is to prepare tables for Django default applications. "What? Django default applications? I thought that we are going to make our own Django application!", you may asked. This is the interesting part. 

Recall that from our previous article, in there we are actually creating a Django project, not yet a Django application. In this Django project there maybe infinite number of Django applications, in which your yet to be created Django application is just one of them. Every Django application will contribute to the functionality of web application generated by the Django project. The beauty of this design is, you can practically plug and play your Django application into any Django project in the future. Django mechanism will take care of making sure your application run in any Django project using it. Very clever, isn't it?

Let have a look of what are Django default applications shipped with every initial Django project. Have a look at the file setting.py and locate the line that says, INSTALLED_APPS = ( ... ). Within the braces are Django default applications, which comprise of (as of Django 1.6.1) :

  1. django.contrib.admin : gives you production ready back-end administrative capabilities for your application model.
    If you are a veteran in web application database development, you will know that, in some web application, the greatest work was done in developing the back-end application. This admin application will only use by admin/staff of the web application, not the user visiting the web. It comprised of many application views/pages that mainly dealt with admin/staff whose sole work is entering data for the application. Because of this, it maybe possible that your client waits for the development of your application for so long without satisfaction. Why? Because (s)he only care of what the web application gives when user visiting the web. And developing your own admin application took so much time effort in your side.
    Django admin application can read you application models, and automatically presented CRUD(=Create, Read, Update and Delete) views for it. You may roll out your own Django admin application, but certainly it's wiser to extend/based your admin application from the existing Django admin application. You can even use the many Django admin customization readily available to spruce up the default admin application.
  2. django.contrib.auth : gives you user authentication and authorization capabilities for your application, required by django.contrib.admin.
    Well, it's not so long ago in my software development career when I have to develop a web application using PHP (without the proper use of many of PHP web framework) and have to implement my own user authentication (identify an existing user) and authorization (gives an identified user a special privileged). And it's not a pleasant experience. It's tedious and error prone. And for many application, you'll have to redo it over and over again.
    With the inclusion of this authorization application built-in, every Django project can use it freely, without any big-effort. A time saver!
  3. django.contrib.contenttypes : gives your applicaton a capability to manage any models installed, required by django.contrib.admin.
    It's the secret why Django admin application able to generate a CRUD page for any models installed on your application on the fly.
  4. django.contrib.sessions : gives  your application an ability to manage session data, required by django.contrib.admin.
    Session was data stored between page request for each visitor. Because HTTP protocol is stateless, there is no way it's able to identify whether a specific request is a continuation from another request. Hence came the session concept, where each visitor was identified uniquely by an ID stored as cookies. This ID was transferred back and forth for each request, allowing web server to identify visitor uniquely.
    Session in Django is implemented as middleware and put in the top most layer of the middlewares, which means it will process first in every application request. If you don't want to use database back-end to implement session, you can remove it from INSTALLED_APPS (but still have to include it in MIDDLEWARE_CLASSES), in which Django will use cookies as the means to store session data.
  5. django.contrib.messages : gives your application flash message capability, required by django.contrib.admin.
    Flash message is a one time message that should be displayed in the next request of an application, which can be from any level such as INFO, WARNING or ERROR. For example when you give an incorrect password in a dialog form and press Login button, the application should display about that error in the next request of the application. And it should be only in the precise subsequent request. Failed to do so will confuse your use, as (s)he will not understand why the login process didn't success or why it kept saying password incorrect although (s)he has successfully logged into your application.
  6. django.contrib.staticfiles : will collect (by copying or creating symbolic link) any static files from each applications defined in your project into STATIC_ROOT directory location defined in setting.py.
    If previously you work only with static website (comprised of only HTML file, served by webserver without any processing from web programming language such as PHP/JSP/Python/ASP/etc.), the notion of static files may be confusing at first. In static website, you were accustomed of having a page link to different page solely by its relative physical page location, which in turn become its page URL. Or in other word, there is one-on-one relation between page URL and page physical location. But in dynamic web application, that's not the case. There is no strict relation whether page with certain URL indeed come from certain physical location. The definition of static files are defined dependently by your web server/ framework.
    Now, that we use Django on Openshift, your static files are defined to come from wsgi/static. There goes, you must add STATIC_ROOT = '../static' to setting.py, and from console/terminal within the directory wsgi/kfimember you must run python manage.py collectstatic which will collect and copy all static files defined in your applications into wsgi/static directory. At the current state of your application, it will copy 69 static files from Django Admin application into wsgi/static. Failed to do this, your admin application will behave well in  localhost, but it will not be able to refer to its static resource (CSS, images or JS files) when it's deployed in Openshift.
    Now, run the command python manage.py collectstatic and make sure static files for Django admin application were copied into wsgi/static.

 

Those are all essential Django Applications shipped by Django. It's not a necessity to use all of that built-in application, but most application will. But having them defined solely in INSTALLED_APPS section within the file static is not enough. You have to prepare for its tables, which is the purpose of the next section of this article.

Prepare Tables for Django Applications

I would loved to have some long talk about the intricacies of this tables preparation step, but let skipped a bit and just use a simple approach first : open terminal/console and execute this command : python manage.py syncdb.

Syncdb

Preparing tables using Syncdb

The above output will resulted in a bunch of tables within your defined database, which in my case it is a PostgreSQL database named kfimember. Those tables (you may want to inspect it now) were belong to Django applications that you explicitly mentioned in  INSTALLED_APPS = ( ... ) within settings.py. As part of that process, django.contrib.auth application asked you to supply the username and password for superuser. Remember it, run Django development server using the command python manage.py runserver and accessed its Django admin application using the url http://localhost:8000/admin, you will see the following login dialog :

Login dialog of Django Admin application

Login dialog of Django Admin application

Login with the aforementioned superuser credential and ... voila! Familiarize yourself with the initial Django admin application. There are good chances that, our next articles will specifically dealt with extending this admin application. 

Django initial Admin application

Django initial Admin application

Try adding a new group or users in this built-in admin application. And just imagine having implement this admin application manually. You may feel already, that our time invested in learning Django indeed already give us a promising result, isn't it? Smile 

Making Our Application Runnable in Openshift

Up until this point, you have successfully configure your local PostgreSQL database and properly connect it into your Django application. But if you try to push this application to Openshift, well, it won't work. The best case is, it will give 500 Internal Server Error, which means you messed up things in your server configuration. Surely, it's because your local PostgreSQL and remote PostgreSQL in Openshift having a different configuration. The question is, how to use a single settings.py to address two different database configuration?

Let's have a look on how it's done!

Configure settings.py for Openshift Environment

The settings.py is a regular Python file. Therefore, you can use any Python construct in it. Here, we are going to use the regular Python os.environ.get() method to query environment for certain variable specific to Openshift (e.g, I am going to use the variable OPENSHIFT_REPO_DIR) . Here is the code:

1
2
3
4
import os
ON_OPENSHIFT = False
if os.environ.get('OPENSHIFT_REPO_DIR'):
    ON_OPENSHIFT = True

Now that we know we are in Openshift or not, we can modify our  DATABASE = { ... } for Openshift specific database configuration, as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
if ON_OPENSHIFT:
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': 'kfimember',
            'USER': 'change_with_your_openshift_postgresql_username',
            'PASSWORD': 'change_with_your_openshift_postgresql_password',
            'HOST': os.environ.get('$OPENSHIFT_POSTGRESQL_DB_HOST',''),
            'PORT': os.environ.get('$OPENSHIFT_POSTGRESQL_DB_PORT',''),
        }
    }
else:
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': 'kfimember',
            'USER' : 'postgres',
            'PASSWORD' : 'change_with_your_local_postgresql_password',
            'HOST' : 'localhost',
            'PORT' : ''
        }
    }

Our next question, how can we know our Openshift PostgreSQL configuration? There are two ways : (1) you can go to your  Openshift Web Console and inspect its PostgreSQL username and password or (2) you can use our old pal rhc tool to do this.

Let use rhc for this, by issuing this command : rhc app-show --app kfimember. It will gives you the following output:

Rhc Showing Up Our PostgreSQL Configuration

Rhc Showing Up Our PostgreSQL Configuration (Username and Password, of course cut out here)

Now you can easily use the output above to fill Openshift PostgreSQL configuration in settings.py.

Commit it and push it to Openshift by issuing this command :

1
2
3
git add .
git commit -am'psql config'
git push origin master

That's all! Your database configuration will be able to runs whether it's locally or in Openshift. 

Final Step : Running syncdb in Openshift via SSH

After pushing your code to Openshift, if you try to access your application using its Openshift URL (mine is in here) it still won't work. It's because your Openshift PostgreSQL still don't have tables required by our built-in Django applications. You have to run python manage.py syncdb in Openshift environment. How we do this? Use rhc ssh command.

Still in your terminal/console, issue this command : rhc ssh --app kfimember. You will be logged into your Openshift box via ssh. There, you just have to go to wsgi/kfimember and issue syncdb command, as follows:

1
2
cd app-root/repo/wsgi/kfimember
python manage.py syncdb

Successfully running those command, will result in a ready to use Django application. You can try accessing again your application in Openshift, and login into its admin application. 

Familiarize yourself with admin application, because as I said previously, it will be our next development areas! Wink

Conclusion

I've come a long way in discussing how to prepare a PostgreSQL configuration for both local and remote database. Beside that, I also explain Django built-in application being setup by default Django manage.py startproject command. Actually, I would like to continute with creating our initial application and model using south, but I think I am going to left it for my subsequent article. 

You can download current step of this application here : kfimember-part-3.zip.

Or, follow its development in Github repo here : kfimember.

Stay tuned!




Leave comments

authimage

Copyright(c) 2014 - PythonBlogs.com
By using this website, you signify your acceptance of Terms and Conditions and Privacy Policy
All rights reserved