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.py
, urls.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:
[shell]
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
[/shell]
First, let's create a parent directory for myblog
, outside of the root myblog
directory. Let's call it django-myblog
:
[shell]
django-myblog/
myblog/
manage.py
...
[/shell]
Second, let's move the myblog
directory into django-myblog
:
[shell]
django-myblog/
myblog/
__init__.py
...
myblog/
manage.py
[/shell]
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.
[python]
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 = '[email protected]',
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'
]
)
[/python]
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:
[shell]
$ 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'
[/shell]
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:
[shell]
$ django-admin.py startproject mysite
[/shell]
Second, let's modify mysite/settings.py
:
[python]
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
)
[/python]
Third, let's modify mysite/urls.py
to put myblog
's URLconf under /blog
:
[python]
urlpatterns = patterns('',
...
url(r'^blog/', include('myblog.urls')),
)
[/python]
Fourth, we run `python manage.py syncdb` to create models for myblog
and run `python manage.py runserver` to start the server:
[shell]
$ 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.
[/shell]
Finally, we can access http://127.0.0.1:8000/blog/ to take a look at our blog's home page:
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.