DEV Community

Cover image for Django Tutorial - Plugins
Sm0ke
Sm0ke

Posted on • Edited on • Originally published at blog.appseed.us

Django Tutorial - Plugins

Hello Coders,

This Django Tutorial describes how to create the first third-party Django library or application similar to the ones listed on PyPI (Python Package Index). For instance, Django itself is a package and during this article, we will learn how to build and reuse a Python project.

Thanks for reading! - Content provided by App Generator.

For newcomers, Django is a Python Web framework built by experienced developers used in production by tech companies like Instagram and Disqus. To make this article more useful and trigger curious minds into programming, an open-source Django sample is provided.


  • Plugins - Short Introduction
  • A real sample: the structure, set-up files
  • Free Sample: Datta Able Django

Django Datta Able - Open-source Django starter provided by AppSeed.


Introduction

The Python Package Index (PyPI) has a vast range of packages you can use in your own Python programs. Check out Django Packages for existing reusable apps you could incorporate into your project. Django itself is also a normal Python package. This means that you can take existing Python packages or Django apps and compose them into your own web project. You only need to write the parts that make your project unique.


Concern

It’s a lot of work to design, build, test, and maintain a web application. Many Python and Django projects share common problems. Wouldn’t it be great if we could save some of this repeated work? Let’s say you were starting a new project that needed a polls app like the one we’ve been working on. How do you make this app reusable?


Structure

The layout of the package will be like this:

< PACKAGE ROOT >               <-- package directory (django-polls)
 |-- polls/                    <-- app directory
 |    |-- migrations/
 |    |    -- __init__.py
 |    |-- static/              <-- static files
 |    |-- templates/           <-- template files
 |    |-- __init__.py
 |    |-- admin.py
 |    |-- apps.py
 |    |-- models.py
 |    |-- tests.py
 |    |-- views.py
 |-- LICENSE
 |-- MANIFEST.in
 |-- README.md
 |-- setup.cfg
 |-- setup.py
Enter fullscreen mode Exit fullscreen mode

Let's start a sample

Create your project (project should look like this):

< PROJECT ROOT >                    <-- project directory
 |-- polls/                         <-- app directory
 |    |-- migrations/
 |    |    -- __init__.py
 |    |-- static/                   <-- static files
 |    |    -- polls/
 |    |         -- styles.css
 |    |-- templates/                <-- template files
 |    |    -- polls/
 |    |         -- index.html
 |    |-- __init__.py
 |    |-- admin.py
 |    |-- apps.py
 |    |-- models.py
 |    |-- tests.py
 |    |-- urls.py
 |    |-- views.py
 |-- core/
 |    |-- __init__.py
 |    |-- settings.py
 |    |-- urls.py
 |    |-- wsgi.py
 |-- manage.py
Enter fullscreen mode Exit fullscreen mode

Now perhaps it is clearer why we chose to have separate template directories for the project and application: everything that is part of the polls application is in polls. It makes the application self-contained and easier to drop into a new project.


The polls directory could now be copied into a new Django project and immediately reused. It’s not quite ready to be published though. For that, we need to package the app to make it easy for others to install.


Packaging your app

To generate the reusable package, the steps to follow are below:

  • Create a parent directory for polls, outside of your Django project. Call this directory django-polls.
  • Move the polls directory into the django-polls directory.
  • Create a file django-polls/README.md with the following contents:

# Polls

Polls is a Django app to conduct Web-based polls. For each question,
visitors can choose between a fixed number of answers.

## Quick start

1. Add "polls" to your INSTALLED_APPS setting like this::

    INSTALLED_APPS = [
        ...
        'polls',
    ]

2. Include the polls URLconf in your project urls.py like this::

    path('polls/', include('polls.urls')),

3. Run ``python manage.py migrate`` to create the polls models.

4. Start the development server and visit http://127.0.0.1:8000/admin/
   to create a poll (you'll need the Admin app enabled).

5. Visit http://127.0.0.1:8000/polls/ to participate in the poll.
Enter fullscreen mode Exit fullscreen mode

  • Create a django-polls/LICENSE file. The code released publicly without a license is useless. Django and many Django-compatible apps are distributed under the BSD license; however, you’re free to pick your own license. Just be aware that your licensing choice will affect who is able to use your code. For MIT Licensed libraries, we can reuse a template provide by Github or write a new one from scratch with all wanted restrictions and rights.

MIT License

Copyright (c) 2021 YOUR COMPANY Here

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
Enter fullscreen mode Exit fullscreen mode

We’ll create setup.cfg and setup.py files that detail how to build and install the app.

django-polls/setup.cfg

[metadata]
name = django-polls
version = 0.1
description = A Django app to conduct Web-based polls.
long_description = file: README.md
url = https://www.example.com/
author = Your Name
author_email = yourname@example.com
license = BSD-3-Clause  # Example license
classifiers =
    Environment :: Web Environment
    Framework :: Django
    Framework :: Django :: X.Y  # Replace "X.Y" as appropriate
    Intended Audience :: Developers
    License :: OSI Approved :: BSD License
    Operating System :: OS Independent
    Programming Language :: Python
    Programming Language :: Python :: 3
    Programming Language :: Python :: 3 :: Only
    Programming Language :: Python :: 3.6
    Programming Language :: Python :: 3.7
    Programming Language :: Python :: 3.8
    Topic :: Internet :: WWW/HTTP
    Topic :: Internet :: WWW/HTTP :: Dynamic Content

[options]
include_package_data = true
packages = find:
Enter fullscreen mode Exit fullscreen mode

django-polls/setup.py

from setuptools import setup, find_packages

setup(
    packages=find_packages(),
    install_requires=[
        'Django',
        # ...
    ],
    include_package_data=True,
    zip_safe=False
)
Enter fullscreen mode Exit fullscreen mode

Only Python modules and packages are included in the package by default. To include additional files, we’ll need to create a MANIFEST.in file. The setuptools docs referred to in the previous step discuss this file in more details. To include the templates, static, the README and LICENSE file, create a django-polls/MANIFEST.in file with the following contents:

django-polls/MANIFEST.in

include LICENSE
include README.rst
recursive-include polls/static *
recursive-include polls/templates *
Enter fullscreen mode Exit fullscreen mode

Optional (but recommended) is to include detailed documentation with your app. Create a directory (django-polls/docs) for future documentation. Add an additional line to django-polls/MANIFEST.in:

django-polls/MANIFEST.in:

...
recursive-include docs *
Enter fullscreen mode Exit fullscreen mode

Note that the docs directory won’t be included in your package unless you add some files to it.


  • Inside django-polls folder run the following command to build your package:

$ python setup.py sdist
Enter fullscreen mode Exit fullscreen mode

This creates a directory called dist and builds your new package, django-polls-0.1.tar.gz.


For more information on packaging, see Python’s Tutorial on Packaging and Distributing Projects.


Datta Able Django

Production-ready Django dashboard coded with authentication, database, and modular codebase on top of a modern UI: Datta Able admin dashboard (free version).

Datta Able rendering is fast in all major browsers. It is passed through a good score in Google Page Speed, Pingdom, GT Metrix. Code passed via w3 validators with all w3 standards. This admin panel is fully responsive and tested on all retina devices.

Datta Able Django - Open-source Django seed project.


Thanks for reading! For more resources, feel free to access:

Top comments (10)

Collapse
 
crearesite profile image
WebsiteMarket

Thank you!
Basically, the setup.cfg and setup.py are critical. The rest of the files are optional.

Collapse
 
sm0ke profile image
Sm0ke

Yes. Adding docs might affect positively the adoption of your software.

Collapse
 
samzhangjy profile image
Sam Zhang

Great article! I have a question about which web framework to choose when building a small (personal) website... Should I use Flask or Django? Thank you!

Collapse
 
sm0ke profile image
Sm0ke

Flask might be a good choice for simple projects.

Collapse
 
samzhangjy profile image
Sam Zhang

Thank you!

Collapse
 
audreyfeldroy profile image
Audrey Roy Greenfeld

Nice writeup! Packaging a Django app is definitely something I think all Django users should try doing if they haven't yet.

Collapse
 
uithemes profile image
ui-themes

The sample looks ... colorful.
Thanks for sharing!

Collapse
 
sm0ke profile image
Sm0ke

Yw!

Collapse
 
rafaacioly profile image
Rafael Acioly

Django Datta Able is great but i didn't get the prices saying "SaaS product not allowed for basic plan", what this mean? i cannot use the dashboard to create my own saas?

Collapse
 
sm0ke profile image
Sm0ke

Hello Rafael

The FREE version can be used for unlimited products, SaaS included.

For SaaS products (commercial version) a company license is required. Just to make sure you really need such a license, feel free to contact AppSeed (email or Discord).

You might don't need one :)