├── .gitignore
├── AUTHORS
├── DESCRIPTION
├── LICENSE
├── MANIFEST.in
├── README.rst
├── appname
├── __init__.py
├── admin.py
├── fixtures
│ └── test_data.json
├── models.py
├── templates
│ └── appname
│ │ └── example_list.html
├── tests
│ ├── __init__.py
│ ├── models.py
│ ├── runtests.py
│ ├── tests.py
│ └── urls.py
├── urls.py
└── views.py
├── bin
└── init.sh
├── lib
└── README.rst
└── setup.py
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | build/
3 | dist/
4 | *egg-info/
5 |
6 |
--------------------------------------------------------------------------------
/AUTHORS:
--------------------------------------------------------------------------------
1 | Current or previous core committers
2 |
3 | * TODO: Add core committers
4 |
5 | Contributors (in alphabetical order)
6 |
7 | * Your name could stand here :)
8 |
--------------------------------------------------------------------------------
/DESCRIPTION:
--------------------------------------------------------------------------------
1 | TODO: Add long description
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | This is free and unencumbered software released into the public domain.
2 |
3 | Anyone is free to copy, modify, publish, use, compile, sell, or
4 | distribute this software, either in source code form or as a compiled
5 | binary, for any purpose, commercial or non-commercial, and by any
6 | means.
7 |
8 | In jurisdictions that recognize copyright laws, the author or authors
9 | of this software dedicate any and all copyright interest in the
10 | software to the public domain. We make this dedication for the benefit
11 | of the public at large and to the detriment of our heirs and
12 | successors. We intend this dedication to be an overt act of
13 | relinquishment in perpetuity of all present and future rights to this
14 | software under copyright law.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
24 | For more information, please refer to
25 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | recursive-include appname *
2 | include README.rst DESCRIPTION
3 | exclude *.orig *.pyc *.wpr
4 |
--------------------------------------------------------------------------------
/README.rst:
--------------------------------------------------------------------------------
1 | Django Reusable App Boilerplate
2 | ===============================
3 |
4 | If you work with Django every day you will want to build reusable apps. This repository should work as a boilerplate for reusable Django apps.
5 |
6 | **Features:**
7 |
8 | * It is ready for test driven development (TDD). Add your first test to tests.py before you implement anything!
9 | * It is ready to be distributed via PyPi
10 |
11 | We are still far from being experts in producing reusable apps. This repository is more or less what we have learned from some inspiring blog posts and from looking at other awesome repositories out there. The whole process of submitting an app based on this boilerplate to PyPi has never been tested (but will be tested soon). Suggestions for enhancements are much appreciated!
12 |
13 | You can find another promising try on the same issue here:
14 |
15 | * `django-packagemaker `_
16 |
17 |
18 | How to use
19 | ==========
20 |
21 | ::
22 |
23 | git clone git://github.com/bitmazk/django-reusable-app-boilerplate yourappname
24 | cd yourappname
25 | ./bin/init.sh
26 | ./yourappname/tests/runtests.py
27 |
28 | The ``init.sh`` a script will ask you for some variables like your desired app-name and other information like keywords, app URL, app author and author email. Your inputs will be used to rename some folders and replace module names and imports in the boilerplate files provided. It will also be used to prepare your ``setup.py`` for easy distribution of your app via PyPi.
29 |
--------------------------------------------------------------------------------
/appname/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | VERSION = (0, 0, 1, 'alpha')
3 | if VERSION[-1] != "final": # pragma: no cover
4 | __version__ = '.'.join(map(str, VERSION))
5 | else: # pragma: no cover
6 | __version__ = '.'.join(map(str, VERSION[:-1]))
7 |
--------------------------------------------------------------------------------
/appname/admin.py:
--------------------------------------------------------------------------------
1 | """Admin classes for appname application."""
2 |
3 | from django.contrib import admin
4 |
5 | from appname.models import Example
6 |
7 |
8 | class ExampleAdmin(admin.ModelAdmin):
9 | """Admin class for Example model class."""
10 | pass
11 |
12 |
13 | admin.site.register(Example, ExampleAdmin)
14 |
--------------------------------------------------------------------------------
/appname/fixtures/test_data.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "pk": 1,
4 | "model": "appname.example",
5 | "fields": {
6 | "text": "Lorem ipsum..."
7 | }
8 | },
9 | {
10 | "pk": 2,
11 | "model": "appname.example",
12 | "fields": {
13 | "text": "Foo bar..."
14 | }
15 | }
16 | ]
17 |
--------------------------------------------------------------------------------
/appname/models.py:
--------------------------------------------------------------------------------
1 | """Models for appname application."""
2 |
3 | from django.db import models
4 |
5 |
6 | class Example(models.Model):
7 | """Example model class."""
8 | text = models.TextField(blank=True, null=True)
9 |
--------------------------------------------------------------------------------
/appname/templates/appname/example_list.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitlabstudio/django-reusable-app-boilerplate/4c706e94cca2ad73d788b282f2232d9a2c8e006b/appname/templates/appname/example_list.html
--------------------------------------------------------------------------------
/appname/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitlabstudio/django-reusable-app-boilerplate/4c706e94cca2ad73d788b282f2232d9a2c8e006b/appname/tests/__init__.py
--------------------------------------------------------------------------------
/appname/tests/models.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitlabstudio/django-reusable-app-boilerplate/4c706e94cca2ad73d788b282f2232d9a2c8e006b/appname/tests/models.py
--------------------------------------------------------------------------------
/appname/tests/runtests.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os
3 | import sys
4 |
5 | from django.conf import settings
6 |
7 |
8 | if not settings.configured:
9 | settings.configure(
10 | DATABASE_ENGINE='sqlite3',
11 | ROOT_URLCONF='appname.tests.urls',
12 | INSTALLED_APPS=[
13 | 'appname',
14 | 'appname.tests',
15 | ]
16 | )
17 |
18 |
19 | from django.test.simple import run_tests
20 |
21 |
22 | def runtests(*test_args):
23 | if not test_args:
24 | test_args = ['tests']
25 | parent = os.path.join(
26 | os.path.dirname(os.path.abspath(__file__)),
27 | "..",
28 | "..",
29 | )
30 | sys.path.insert(0, parent)
31 | failures = run_tests(test_args, verbosity=1, interactive=True)
32 | sys.exit(failures)
33 |
34 |
35 | if __name__ == '__main__':
36 | runtests(*sys.argv[1:])
37 |
--------------------------------------------------------------------------------
/appname/tests/tests.py:
--------------------------------------------------------------------------------
1 | """Tests for appname application."""
2 |
3 | from unittest import TestCase
4 | from django.test import TestCase as DjangoTestCase
5 |
6 |
7 | class TestSuiteTestCase(TestCase):
8 | """General test to make sure that the setup works."""
9 | def test_test_suite_can_be_run(self):
10 | self.assertTrue(True)
11 |
12 |
13 | class ExampleTestCase(DjangoTestCase):
14 | """Tests for Example model class."""
15 | fixtures = ['test_data']
16 | urls = 'appname.tests.urls'
17 |
18 | def test_example_view_is_callable(self):
19 | resp = self.client.get('/example/')
20 | self.assertEqual(resp.status_code, 200)
21 |
--------------------------------------------------------------------------------
/appname/tests/urls.py:
--------------------------------------------------------------------------------
1 | from django.conf.urls.defaults import *
2 |
3 |
4 | urlpatterns = patterns('',
5 | url(r'^example/', include('appname.urls')),
6 | )
7 |
--------------------------------------------------------------------------------
/appname/urls.py:
--------------------------------------------------------------------------------
1 | """URLs for appname application."""
2 |
3 | from django.conf.urls.defaults import *
4 |
5 |
6 | urlpatterns = patterns('appname.views',
7 | url(r'^$', view='index', name='appname_index'),
8 | )
9 |
--------------------------------------------------------------------------------
/appname/views.py:
--------------------------------------------------------------------------------
1 | """Views for appname application."""
2 |
3 | from django.http import HttpResponse, Http404
4 | from django.shortcuts import get_object_or_404
5 | from django.views.generic.list_detail import object_list
6 |
7 |
8 | from appname.models import Example
9 |
10 |
11 | def index(request, template_name='appname/example_list.html'):
12 | """Index view."""
13 | qs = Example.objects.all()
14 |
15 | try:
16 | page = int(request.GET.get('page', 0))
17 | except ValueError:
18 | raise Http404
19 |
20 | return object_list(
21 | request,
22 | queryset=qs,
23 | template_object_name='example',
24 | paginate_by=10,
25 | page=page,
26 | )
27 |
--------------------------------------------------------------------------------
/bin/init.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | echo "Name of your reusable app:"
3 | read APPNAME
4 | echo "Keywords for your app:"
5 | read KEYWORDS
6 | echo "Author of your app:"
7 | read AUTHOR
8 | echo "Author email of your app:"
9 | read AUTHOREMAIL
10 | echo "URL for your app:"
11 | read URL
12 |
13 | echo "Deleting .git folder"
14 | rm -rf .git
15 |
16 | echo "Replacing README.rst"
17 | rm README.rst
18 | mv lib/README.rst .
19 | rm -rf lib
20 |
21 | echo "Replacing strings in files..."
22 | sed -i "s/the_keywords/$KEYWORDS/g" setup.py
23 | sed -i "s/the_author/$AUTHOR/g" setup.py
24 | sed -i "s/the_email/$AUTHOREMAIL/g" setup.py
25 | sed -i "s@the_url@$URL@g" setup.py
26 | find . -type f -exec sed -i "s/appname/$APPNAME/g" {} +
27 |
28 | echo "Renaming folders..."
29 | mv appname/templates/appname/ appname/templates/$APPNAME
30 | mv appname $APPNAME
31 |
32 | echo "Deleting bin folder..."
33 | rm -rf bin
34 |
35 | echo "Initialize new git repository..."
36 | git init
37 | git add .
38 | git commit -am "Initial commit"
39 |
40 | echo "Done! Please edit AUTHORS, DESCRIPTION and README.rst now."
41 |
--------------------------------------------------------------------------------
/lib/README.rst:
--------------------------------------------------------------------------------
1 | TODO: Add app name
2 | ==================
3 |
4 | TODO: Add project readme.
5 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | import os
2 | from setuptools import setup, find_packages
3 | import appname
4 |
5 |
6 | def read(fname):
7 | try:
8 | return open(os.path.join(os.path.dirname(__file__), fname)).read()
9 | except IOError:
10 | return ''
11 |
12 |
13 | setup(
14 | name="appname",
15 | version=appname.__version__,
16 | description=read('DESCRIPTION'),
17 | long_description=read('README.rst'),
18 | keywords='the_keywords',
19 | packages=find_packages(),
20 | author='the_author',
21 | author_email='the_email',
22 | url="the_url",
23 | include_package_data=True,
24 | test_suite='appname.tests.runtests.runtests',
25 | )
26 |
--------------------------------------------------------------------------------