Package Your Python Django Application into a Reusable Component

Save Time by Writing and Using Reusable Python Django Apps

It’s not trivial to design, develop and maintain a web application. Lots of features and aspects have to be handled properly in order for a web application to succeed. To name a few, the features that are common to almost every web application are user management, third-party oauth sign in / sign up and admin site. Since so many common problems have to be solved in any web application over and over again, it makes sense to make them reusable components / packages so that a new web application can simply leverage the existing code to save time during development.

Fortunately, the Python Package Index (pypi) provides numerous packages you can use in your own application. More specifically, the Django Packages list all the reusables Django apps you can integrate into your own project. Finding and using a proper Django package is often better and more time-efficient than writing one yourself.

In this article, we are going to learn how to make our current myblog Django application become a reusable Django package so that you or someone else can use it in his or her own project.

Package and App

Before we start, we should clarify a critical point about packages and apps. A Python package is a logical group of Python code that’s easy to re-use. A package often contains multiple Python files that are called modules.

Usually, we use a module or a package by importing it like import myblog.views or from myblog import views. To make a Python directory such as myblog become a package, we put a special file __init__.py into it even if the directory is empty.

A Django app is just a Python package designed to be used inside a Django project. Usually, a Django app follows common Django conventions such as including models.pyurls.py and views.py.

The term packaging means wrapping the Django app into a deployable Python package so that others can easily integrate it into their own project.

Extract the App Code

After our previous tutorial, the current structure of our application myblog should look like this:

myblog/
  manage.py
  myblog/
    __init__.py
    admin.py
    models.py
    settings.py
    static/
    myblog/
      background.jpg
      style.css
      templates/
        index.html
        post/
          detail.html
          upload.html
          tests.py
          urls.py
          views.py
          wsgi.py

First, let’s create a parent directory for myblog, outside of the root myblog directory. Let’s call it django-myblog:

django-myblog/
  myblog/
    manage.py
    ...

Second, let’s move the myblog directory into django-myblog:

django-myblog/
  myblog/
  __init__.py
  ...
  myblog/
    manage.py

Third, create a file django-myblog/README.rst with the following content:

=====
Myblog
=====

Myblog is a simple demo of Django's basic usage.

Quick start
-----------

1. Add "myblog" to INSTALLED_APPS:
  INSTALLED_APPS = {
    ...
    'myblog'
  }

2. Include the myblog URLconf in urls.py:
  url(r'^myblog/', include('myblog.urls'))

3. Run `python manage.py syncdb` to create myblog's models.

4. Run the development server and access http://127.0.0.1:8000/admin/ to
    manage blog posts.

5. Access http://127.0.0.1:8000/myblog/ to view a list of most recent posts.

Fourth, create a license file django-myblog/LICENSE for your reusable app. Usually Django apps are distributed under the BSD license but you’re free to choose any one.

Fifth, create django-myblog/setup.py to specify instruction about how to install the app which is used by Distribute.

import os
from setuptools import setup
 
README = open(os.path.join(os.path.dirname(__file__), 'README.rst')).read()
 
# Allow setup.py to be run from any path
os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
 
setup(
    name = 'django-myblog',
    version = '0.1',
    packages = ['myblog'],
    include_package_data = True,
    license = 'BSD License',
    description = 'A simple Django app demo.',
    long_description = README,
    url = 'http://www.example.com/',
    author = 'Your Name',
    author_email = 'yourname@example.com',
    classifiers =[
        'Environment :: Web Environment',
        'Framework :: Django',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: BSD License', # example license
        'Operating System :: OS Independent',
        'Programming Language :: Python',
        'Programming Language :: Python :: 2.6',
        'Programming Language :: Python :: 2.7',
        'Topic :: Internet :: WWW/HTTP',
        'Topic :: Internet :: WWW/HTTP :: Dynamic Content'
    ]
)

Sixth, create django-myblog/MANIFEST.in to include the text files and static files in our package:

include LICENSE
include README.rst
recursive-include myblog/static *
recursive-include myblog/templates *
recursive-include docs *

Notice we also included a directory docs in MANIFEST.in. This directory will contain documentation for our reusable app in the future. For now, let’s create an empty directory django-myblog/docs.

Finally, we build our Python package:

$ python setup.py build
running build
running build_py
creating build
creating build/lib
creating build/lib/myblog
copying myblog/__init__.py -> build/lib/myblog
copying myblog/admin.py -> build/lib/myblog
copying myblog/models.py -> build/lib/myblog
copying myblog/settings.py -> build/lib/myblog
copying myblog/tests.py -> build/lib/myblog
copying myblog/urls.py -> build/lib/myblog
copying myblog/views.py -> build/lib/myblog
copying myblog/wsgi.py -> build/lib/myblog
running egg_info
writing django_myblog.egg-info/PKG-INFO
writing top-level names to django_myblog.egg-info/top_level.txt
writing dependency_links to django_myblog.egg-info/dependency_links.txt
reading manifest file 'django_myblog.egg-info/SOURCES.txt'
writing manifest file 'django_myblog.egg-info/SOURCES.txt'

Use django-myblog in a New Django Web Application

Suppose you are going to start a new Django project and it’s going to use the functionality in myblog. You can simply reuse django-myblog we just built in your new project.

First, let’s create a new Django project:

$ django-admin.py startproject mysite

Second, let’s modify mysite/settings.py:

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myblog', # Include 'myblog' into mysite
    'django.contrib.admin', # Enable the admin site
    'django.contrib.admindocs', # Enable the documentation for admin site
)

Third, let’s modify mysite/urls.py to put myblog‘s URLconf under /blog:

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

Fourth, we run `python manage.py syncdb` to create models for myblog and run `python manage.py runserver` to start the server:

$ python manage.py syncdb
Creating tables ...
Creating table auth_permission
Creating table auth_group_permissions
Creating table auth_group
Creating table auth_user_groups
Creating table auth_user_user_permissions
Creating table auth_user
Creating table django_content_type
Creating table django_session
Creating table django_site
Creating table myblog_post
Creating table myblog_comment
 
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 'xiaonuogantan'): root
Email address:
Password:
Password (again):
Superuser created successfully.
Installing custom SQL ...
Installing indexes ...
Installed 0 object(s) from 0 fixture(s)
 
$ python manage.py runserver
Validating models...
 
0 errors found
August 21, 2013 - 12:03:10
Django version 1.5.1, using settings 'mysite.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Finally, we can access http://127.0.0.1:8000/blog/ to take a look at our blog’s home page:
Use django-myblog in a New Django Web Application

Summary and Tips

In this article, we learned how to package our myblog app into a reusable component and how to use it in a new django project. It’s always a good idea to write reusable Django apps since you can reuse the same code in new projects, thus saving a significant amount of time. Since Python Package Index (pypi) and Django Packages provide comprehensive lists of reusable Python and Django apps, you should check them out before starting any new project.

Leave a Reply

Your email address will not be published. Required fields are marked *