Skip to content

Commit 5f22642

Browse files
committed
Yummy vanilla goodness.
0 parents  commit 5f22642

19 files changed

+802
-0
lines changed

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
*.pyc
2+
*.db
3+
MANIFEST
4+
dist/
5+
build/
6+
env/
7+
*.egg-info/

README.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Django Vanilla Views
2+
3+
**Beautifully simple class based views.**
4+
5+
**Author:** Tom Christie, [Follow me on Twitter][1].
6+
7+
8+
View --+------------------------- RedirectView
9+
|
10+
+-- GenericView -------+-- TemplateView
11+
| |
12+
| +-- FormView
13+
|
14+
+-- GenericModelView --+-- ListView
15+
|
16+
+-- DetailView
17+
|
18+
+-- CreateView
19+
|
20+
+-- UpdateView
21+
|
22+
+-- DeleteView
23+
24+
Django's generic class based view implementation is unneccesarily complicated.
25+
26+
Django vanilla views gives you the same benefits of using class based views, but with:
27+
28+
* No mixin classes.
29+
* No calls to `super()`.
30+
* A sane class heirarchy.
31+
* A stripped down API.
32+
* Simpler method implementations, with less magical behavior.
33+
34+
Note that the package does not yet include the date based generic views.
35+
36+
`django-vanilla-views` should currently be considered in draft. A properly tested and documented beta release is planned.
37+
38+
# Installation
39+
40+
Install using pip.
41+
42+
pip install django-vanilla-views
43+
44+
Import and use the views.
45+
46+
from vanilla import ListView, DetailView
47+
48+
# License
49+
50+
Copyright © Tom Christie.
51+
52+
All rights reserved.
53+
54+
Redistribution and use in source and binary forms, with or without
55+
modification, are permitted provided that the following conditions are met:
56+
57+
Redistributions of source code must retain the above copyright notice, this
58+
list of conditions and the following disclaimer.
59+
Redistributions in binary form must reproduce the above copyright notice, this
60+
list of conditions and the following disclaimer in the documentation and/or
61+
other materials provided with the distribution.
62+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
63+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
64+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
65+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
66+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
67+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
68+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
69+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
70+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
71+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
72+
73+
[1]: http://twitter.com/_tomchristie

example/example/__init__.py

Whitespace-only changes.

example/example/notes/__init__.py

Whitespace-only changes.

example/example/notes/models.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from django.db import models
2+
3+
class Note(models.Model):
4+
created = models.DateTimeField(auto_now_add=True)
5+
message = models.CharField(max_length=100)
6+
complete = models.BooleanField(default=False)

example/example/settings.py

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
# Django settings for example project.
2+
3+
DEBUG = True
4+
TEMPLATE_DEBUG = DEBUG
5+
6+
ADMINS = (
7+
# ('Your Name', '[email protected]'),
8+
)
9+
10+
MANAGERS = ADMINS
11+
12+
DATABASES = {
13+
'default': {
14+
'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
15+
'NAME': 'sqlite3.db', # Or path to database file if using sqlite3.
16+
# The following settings are not used with sqlite3:
17+
'USER': '',
18+
'PASSWORD': '',
19+
'HOST': '', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
20+
'PORT': '', # Set to empty string for default.
21+
}
22+
}
23+
24+
# Hosts/domain names that are valid for this site; required if DEBUG is False
25+
# See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts
26+
ALLOWED_HOSTS = []
27+
28+
# Local time zone for this installation. Choices can be found here:
29+
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
30+
# although not all choices may be available on all operating systems.
31+
# In a Windows environment this must be set to your system time zone.
32+
TIME_ZONE = 'America/Chicago'
33+
34+
# Language code for this installation. All choices can be found here:
35+
# http://www.i18nguy.com/unicode/language-identifiers.html
36+
LANGUAGE_CODE = 'en-us'
37+
38+
SITE_ID = 1
39+
40+
# If you set this to False, Django will make some optimizations so as not
41+
# to load the internationalization machinery.
42+
USE_I18N = True
43+
44+
# If you set this to False, Django will not format dates, numbers and
45+
# calendars according to the current locale.
46+
USE_L10N = True
47+
48+
# If you set this to False, Django will not use timezone-aware datetimes.
49+
USE_TZ = True
50+
51+
# Absolute filesystem path to the directory that will hold user-uploaded files.
52+
# Example: "/var/www/example.com/media/"
53+
MEDIA_ROOT = ''
54+
55+
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
56+
# trailing slash.
57+
# Examples: "http://example.com/media/", "http://media.example.com/"
58+
MEDIA_URL = ''
59+
60+
# Absolute path to the directory static files should be collected to.
61+
# Don't put anything in this directory yourself; store your static files
62+
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
63+
# Example: "/var/www/example.com/static/"
64+
STATIC_ROOT = ''
65+
66+
# URL prefix for static files.
67+
# Example: "http://example.com/static/", "http://static.example.com/"
68+
STATIC_URL = '/static/'
69+
70+
# Additional locations of static files
71+
STATICFILES_DIRS = (
72+
# Put strings here, like "/home/html/static" or "C:/www/django/static".
73+
# Always use forward slashes, even on Windows.
74+
# Don't forget to use absolute paths, not relative paths.
75+
)
76+
77+
# List of finder classes that know how to find static files in
78+
# various locations.
79+
STATICFILES_FINDERS = (
80+
'django.contrib.staticfiles.finders.FileSystemFinder',
81+
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
82+
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
83+
)
84+
85+
# Make this unique, and don't share it with anybody.
86+
SECRET_KEY = 'qv!8w33y)!_!w&&5ve)l)k01mzivs*+i8ms32r7x$0z2qmawbt'
87+
88+
# List of callables that know how to import templates from various sources.
89+
TEMPLATE_LOADERS = (
90+
'django.template.loaders.filesystem.Loader',
91+
'django.template.loaders.app_directories.Loader',
92+
# 'django.template.loaders.eggs.Loader',
93+
)
94+
95+
MIDDLEWARE_CLASSES = (
96+
'django.middleware.common.CommonMiddleware',
97+
'django.contrib.sessions.middleware.SessionMiddleware',
98+
'django.middleware.csrf.CsrfViewMiddleware',
99+
'django.contrib.auth.middleware.AuthenticationMiddleware',
100+
'django.contrib.messages.middleware.MessageMiddleware',
101+
# Uncomment the next line for simple clickjacking protection:
102+
# 'django.middleware.clickjacking.XFrameOptionsMiddleware',
103+
)
104+
105+
ROOT_URLCONF = 'example.urls'
106+
107+
# Python dotted path to the WSGI application used by Django's runserver.
108+
WSGI_APPLICATION = 'example.wsgi.application'
109+
110+
TEMPLATE_DIRS = (
111+
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
112+
# Always use forward slashes, even on Windows.
113+
# Don't forget to use absolute paths, not relative paths.
114+
'templates',
115+
)
116+
117+
INSTALLED_APPS = (
118+
'django.contrib.auth',
119+
'django.contrib.contenttypes',
120+
'django.contrib.sessions',
121+
'django.contrib.sites',
122+
'django.contrib.messages',
123+
'django.contrib.staticfiles',
124+
'example.notes'
125+
)
126+
127+
# A sample logging configuration. The only tangible logging
128+
# performed by this configuration is to send an email to
129+
# the site admins on every HTTP 500 error when DEBUG=False.
130+
# See http://docs.djangoproject.com/en/dev/topics/logging for
131+
# more details on how to customize your logging configuration.
132+
LOGGING = {
133+
'version': 1,
134+
'disable_existing_loggers': False,
135+
'filters': {
136+
'require_debug_false': {
137+
'()': 'django.utils.log.RequireDebugFalse'
138+
}
139+
},
140+
'handlers': {
141+
'mail_admins': {
142+
'level': 'ERROR',
143+
'filters': ['require_debug_false'],
144+
'class': 'django.utils.log.AdminEmailHandler'
145+
}
146+
},
147+
'loggers': {
148+
'django.request': {
149+
'handlers': ['mail_admins'],
150+
'level': 'ERROR',
151+
'propagate': True,
152+
},
153+
}
154+
}

example/example/urls.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from django.conf.urls import patterns, include, url
2+
from vanilla import CreateView, ListView
3+
from example.notes.models import Note
4+
5+
urlpatterns = patterns('',
6+
url(r'^$', ListView.as_view(model=Note), name='note_list'),
7+
url(r'^create$', CreateView.as_view(model=Note), name='note_create'),
8+
)

example/example/wsgi.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
"""
2+
WSGI config for example project.
3+
4+
This module contains the WSGI application used by Django's development server
5+
and any production WSGI deployments. It should expose a module-level variable
6+
named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover
7+
this application via the ``WSGI_APPLICATION`` setting.
8+
9+
Usually you will have the standard Django WSGI application here, but it also
10+
might make sense to replace the whole Django WSGI application with a custom one
11+
that later delegates to the Django one. For example, you could introduce WSGI
12+
middleware here, or combine a Django application with an application of another
13+
framework.
14+
15+
"""
16+
import os
17+
18+
# We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks
19+
# if running multiple sites in the same mod_wsgi process. To fix this, use
20+
# mod_wsgi daemon mode with each site in its own daemon process, or use
21+
# os.environ["DJANGO_SETTINGS_MODULE"] = "example.settings"
22+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "example.settings")
23+
24+
# This application object is used by any WSGI server configured to use this
25+
# file. This includes Django's development server, if the WSGI_APPLICATION
26+
# setting points here.
27+
from django.core.wsgi import get_wsgi_application
28+
application = get_wsgi_application()
29+
30+
# Apply WSGI middleware here.
31+
# from helloworld.wsgi import HelloWorldApplication
32+
# application = HelloWorldApplication(application)

example/manage.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/usr/bin/env python
2+
import os
3+
import sys
4+
5+
if __name__ == "__main__":
6+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "example.settings")
7+
8+
from django.core.management import execute_from_command_line
9+
10+
execute_from_command_line(sys.argv)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<html>
2+
{{form}}
3+
</html>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<html>
2+
<table>
3+
<tr><th>Message</th><th>Completed</th></tr>
4+
{% for note in note_list %}
5+
<tr><td>{{ note.message }}</td><td>{{ note.completed }}</td></tr>
6+
{% endfor %}
7+
</table>
8+
</html>

manage.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/usr/bin/env python
2+
import os
3+
import sys
4+
5+
if __name__ == "__main__":
6+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "testsettings")
7+
8+
from django.core.management import execute_from_command_line
9+
10+
execute_from_command_line(sys.argv)

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Django>=1.3

setup.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
from setuptools import setup
5+
import re
6+
import os
7+
import sys
8+
9+
10+
name = 'django-vanilla-views'
11+
package = 'vanilla'
12+
description = ''
13+
url = 'http://github.com/tomchristie/django-vanilla-views/'
14+
author = 'Tom Christie'
15+
author_email = '[email protected]'
16+
license = 'BSD'
17+
install_requires = []
18+
19+
20+
def get_version(package):
21+
"""
22+
Return package version as listed in `__version__` in `init.py`.
23+
"""
24+
init_py = open(os.path.join(package, '__init__.py')).read()
25+
return re.search("^__version__ = ['\"]([^'\"]+)['\"]", init_py, re.MULTILINE).group(1)
26+
27+
28+
def get_packages(package):
29+
"""
30+
Return root package and all sub-packages.
31+
"""
32+
return [dirpath
33+
for dirpath, dirnames, filenames in os.walk(package)
34+
if os.path.exists(os.path.join(dirpath, '__init__.py'))]
35+
36+
37+
def get_package_data(package):
38+
"""
39+
Return all files under the root package, that are not in a
40+
package themselves.
41+
"""
42+
walk = [(dirpath.replace(package + os.sep, '', 1), filenames)
43+
for dirpath, dirnames, filenames in os.walk(package)
44+
if not os.path.exists(os.path.join(dirpath, '__init__.py'))]
45+
46+
filepaths = []
47+
for base, filenames in walk:
48+
filepaths.extend([os.path.join(base, filename)
49+
for filename in filenames])
50+
return {package: filepaths}
51+
52+
53+
if sys.argv[-1] == 'publish':
54+
os.system("python setup.py sdist upload")
55+
args = {'version': get_version(package)}
56+
print "You probably want to also tag the version now:"
57+
print " git tag -a %(version)s -m 'version %(version)s'" % args
58+
print " git push --tags"
59+
sys.exit()
60+
61+
62+
setup(
63+
name=name,
64+
version=get_version(package),
65+
url=url,
66+
license=license,
67+
description=description,
68+
author=author,
69+
author_email=author_email,
70+
packages=get_packages(package),
71+
package_data=get_package_data(package),
72+
install_requires=install_requires
73+
)

0 commit comments

Comments
 (0)