diff --git a/example/manage.py b/example/manage.py
index 41e1821..72c4bb0 100755
--- a/example/manage.py
+++ b/example/manage.py
@@ -1,21 +1,22 @@
#!/usr/bin/env python
-
import os
import sys
-try:
- import faq
-except ImportError:
- sys.stderr.write("django-fack isn't installed; trying to use a source checkout in ../fack.")
- sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
-
-from django.core.management import execute_manager
-try:
- import settings # Assumed to be in the same directory.
-except ImportError:
- import sys
- sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
- sys.exit(1)
-
if __name__ == "__main__":
- execute_manager(settings)
+ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "example.settings")
+ try:
+ from django.core.management import execute_from_command_line
+ except ImportError:
+ # The above import may fail for some other reason. Ensure that the
+ # issue is really that Django is missing to avoid masking other
+ # exceptions on Python 2.
+ try:
+ import django
+ except ImportError:
+ raise ImportError(
+ "Couldn't import Django. Are you sure it's installed and "
+ "available on your PYTHONPATH environment variable? Did you "
+ "forget to activate a virtual environment?"
+ )
+ raise
+ execute_from_command_line(sys.argv)
diff --git a/example/settings.py b/example/settings.py
index f74b299..9c723e3 100644
--- a/example/settings.py
+++ b/example/settings.py
@@ -1,35 +1,121 @@
-#
-# A minimal settings file that ought to work out of the box for just about
-# anyone trying this project. It's deliberately missing most settings to keep
-# everything simple.
-#
-# A real app would have a lot more settings. The only important bit as far as
-# django-FAQ is concerned is to have `faq` in INSTALLED_APPS.
-#
+"""
+Django settings for example project.
+
+Generated by 'django-admin startproject' using Django 1.11.20.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/1.11/topics/settings/
+
+For the full list of settings and their values, see
+https://docs.djangoproject.com/en/1.11/ref/settings/
+"""
import os
-PROJECT_DIR = os.path.dirname(__file__)
-DEBUG = TEMPLATE_DEBUG = True
+# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
+BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+
+
+# Quick-start development settings - unsuitable for production
+# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
+
+# SECURITY WARNING: keep the secret key used in production secret!
+SECRET_KEY = '98k_4t655_&p97^95-q#)=27yb4g!htrwu^c84y_@$yv3w!-qs'
+
+# SECURITY WARNING: don't run with debug turned on in production!
+DEBUG = True
+
+ALLOWED_HOSTS = []
+
+
+# Application definition
+
+INSTALLED_APPS = [
+ 'django.contrib.admin',
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django.contrib.messages',
+ 'django.contrib.staticfiles',
+ 'fack',
+]
+
+MIDDLEWARE = [
+ 'django.middleware.security.SecurityMiddleware',
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.middleware.common.CommonMiddleware',
+ 'django.middleware.csrf.CsrfViewMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'django.contrib.messages.middleware.MessageMiddleware',
+ 'django.middleware.clickjacking.XFrameOptionsMiddleware',
+]
+
+ROOT_URLCONF = 'example.urls'
+
+TEMPLATES = [
+ {
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
+ 'DIRS': [os.path.join(BASE_DIR, 'example', 'templates')],
+ 'APP_DIRS': True,
+ 'OPTIONS': {
+ 'context_processors': [
+ 'django.template.context_processors.debug',
+ 'django.template.context_processors.request',
+ 'django.contrib.auth.context_processors.auth',
+ 'django.contrib.messages.context_processors.messages',
+ ],
+ },
+ },
+]
+
+WSGI_APPLICATION = 'example.wsgi.application'
+
+
+# Database
+# https://docs.djangoproject.com/en/1.11/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
- 'NAME': os.path.join(PROJECT_DIR, 'faq.db'),
+ 'NAME': os.path.join(BASE_DIR, 'example', 'db.sqlite3'),
}
}
-SITE_ID = 1
-SECRET_KEY = 'c#zi(mv^n+4te_sy$hpb*zdo7#f7ccmp9ro84yz9bmmfqj9y*c'
-ROOT_URLCONF = 'urls'
-TEMPLATE_DIRS = (
- [os.path.join(PROJECT_DIR, "templates")]
-)
-INSTALLED_APPS = (
- 'django.contrib.auth',
- 'django.contrib.contenttypes',
- 'django.contrib.sessions',
- 'django.contrib.sites',
- 'django.contrib.admin',
- 'fack',
-)
\ No newline at end of file
+
+# Password validation
+# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
+
+AUTH_PASSWORD_VALIDATORS = [
+ {
+ 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
+ },
+ {
+ 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
+ },
+ {
+ 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
+ },
+ {
+ 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
+ },
+]
+
+
+# Internationalization
+# https://docs.djangoproject.com/en/1.11/topics/i18n/
+
+LANGUAGE_CODE = 'en-us'
+
+TIME_ZONE = 'UTC'
+
+USE_I18N = True
+
+USE_L10N = True
+
+USE_TZ = True
+
+
+# Static files (CSS, JavaScript, Images)
+# https://docs.djangoproject.com/en/1.11/howto/static-files/
+
+STATIC_URL = '/static/'
diff --git a/example/templates/home.html b/example/templates/home.html
index aec8ba0..dba9b39 100644
--- a/example/templates/home.html
+++ b/example/templates/home.html
@@ -1,7 +1,6 @@
{% extends "faq/base.html" %}
{% block body %}
-{% load url from future %}
Welcome to the django-fack example project
If you aren't seeing any data below, or if you're getting random 404s, make
@@ -40,7 +39,7 @@
Welcome to the django-fack example project
- Speaking of the admin, here's the FAQ admin.
+ Speaking of the admin, here's the FAQ admin.
Remember that you can clean up submitted questions in the admin before the
diff --git a/example/urls.py b/example/urls.py
index 16b2e00..d1186c7 100644
--- a/example/urls.py
+++ b/example/urls.py
@@ -1,21 +1,24 @@
-from django.conf.urls.defaults import patterns, url, include
-from django.contrib import admin; admin.autodiscover()
-from django.conf import settings
+"""example URL Configuration
+
+The `urlpatterns` list routes URLs to views. For more information please see:
+ https://docs.djangoproject.com/en/1.11/topics/http/urls/
+Examples:
+Function views
+ 1. Add an import: from my_app import views
+ 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
+Class-based views
+ 1. Add an import: from other_app.views import Home
+ 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
+Including another URLconf
+ 1. Import the include() function: from django.conf.urls import url, include
+ 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
+"""
+from django.conf.urls import include, url
+from django.contrib import admin
from django.views.generic import TemplateView
-urlpatterns = patterns('',
- # Just a simple example "home" page to show a bit of help/info.
- url(r'^$', TemplateView.as_view(template_name="home.html")),
-
- # This is the URLconf line you'd put in a real app to include the FAQ views.
+urlpatterns = [
+ url(r'^admin/', admin.site.urls),
url(r'^faq/', include('fack.urls')),
-
- # Everybody wants an admin to wind a piece of string around.
- url(r'^admin/', include(admin.site.urls)),
-
- # Normally we'd do this if DEBUG only, but this is just an example app.
- url(regex = r'^static/(?P.*)$',
- view = 'django.views.static.serve',
- kwargs = {'document_root': settings.MEDIA_ROOT}
- ),
-)
\ No newline at end of file
+ url(r'^$', TemplateView.as_view(template_name="home.html")),
+]
diff --git a/example/wsgi.py b/example/wsgi.py
new file mode 100644
index 0000000..c33c08a
--- /dev/null
+++ b/example/wsgi.py
@@ -0,0 +1,16 @@
+"""
+WSGI config for example project.
+
+It exposes the WSGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/
+"""
+
+import os
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "example.settings")
+
+application = get_wsgi_application()
diff --git a/fack/__init__.py b/fack/__init__.py
index e43be03..58d478a 100644
--- a/fack/__init__.py
+++ b/fack/__init__.py
@@ -1 +1 @@
-__version__ = '1.0'
\ No newline at end of file
+__version__ = '1.2.0'
diff --git a/fack/tests/test_views.py b/fack/tests/test_views.py
index 4a71651..c5c2d33 100644
--- a/fack/tests/test_views.py
+++ b/fack/tests/test_views.py
@@ -13,12 +13,40 @@ class FAQViewTests(django.test.TestCase):
def setUp(self):
# Make some test templates available.
- self._oldtd = settings.TEMPLATE_DIRS
- settings.TEMPLATE_DIRS = [os.path.join(os.path.dirname(__file__), 'templates')]
+ try:
+ self._original_templates = settings.TEMPLATES
+ settings.TEMPLATES = [
+ {
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
+ 'DIRS': [
+ os.path.normpath(os.path.join(os.path.dirname(__file__), 'templates')),
+ ],
+ 'APP_DIRS': True,
+ 'OPTIONS': {
+ 'context_processors': [
+ 'django.contrib.auth.context_processors.auth',
+ 'django.template.context_processors.debug',
+ 'django.template.context_processors.i18n',
+ 'django.template.context_processors.media',
+ 'django.template.context_processors.static',
+ 'django.template.context_processors.tz',
+ 'django.contrib.messages.context_processors.messages',
+ ],
+ },
+ },
+ ]
+ except AttributeError:
+ # Old style TEMPLATE_DIRS
+ self._original_templates = None
+ self._oldtd = settings.TEMPLATE_DIRS
+ settings.TEMPLATE_DIRS = [os.path.join(os.path.dirname(__file__), 'templates')]
def tearDown(self):
- settings.TEMPLATE_DIRS = self._oldtd
-
+ if self._original_templates is not None:
+ settings.TEMPLATES = self._original_templates
+ else:
+ settings.TEMPLATE_DIRS = self._oldtd
+
def test_submit_faq_get(self):
response = self.client.get('/submit/')
self.assertEqual(response.status_code, 200)
diff --git a/fack/urls.py b/fack/urls.py
index 39dae9b..7167dc4 100644
--- a/fack/urls.py
+++ b/fack/urls.py
@@ -2,11 +2,15 @@
try:
from django.conf.urls.defaults import *
-except:
- from django.conf.urls import url, patterns
+except ImportError:
+ from django.conf.urls import url
+ try:
+ from django.conf.urls import patterns
+ except ImportError:
+ patterns = None
from . import views
-urlpatterns = patterns('',
+urls = [
url(regex = r'^$',
view = views.TopicList.as_view(),
name = 'faq_topic_list',
@@ -27,4 +31,9 @@
view = views.QuestionDetail.as_view(),
name = 'faq_question_detail',
),
-)
+]
+
+if patterns is None:
+ urlpatterns = urls
+else:
+ urlpatterns = patterns('', *urls)
diff --git a/setup.py b/setup.py
index 194fce5..131bfac 100644
--- a/setup.py
+++ b/setup.py
@@ -6,7 +6,7 @@ def read(fname):
setup(
name = 'django-fack',
- version = '1.1',
+ version = '1.2.0',
description = 'A simple FAQ application for Django sites.',
long_description = read('README.rst'),
license = "BSD",
@@ -16,6 +16,7 @@ def read(fname):
url = 'http://django-fack.rtfd.org/',
packages = find_packages(exclude=['example']),
+ include_package_data=True,
zip_safe = False,
classifiers = [
diff --git a/tox.ini b/tox.ini
index 11bf405..c1983a9 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,6 +1,6 @@
[tox]
downloadcache = .tox/_download/
-envlist = py27-dj{14,15,16,17,18,19}, docs
+envlist = py27-dj{14,15,16,17,18,19,110,111}, py35-dj{18,111}, docs
[testenv]
deps =
@@ -11,6 +11,8 @@ deps =
dj17: Django>=1.7,<1.8
dj18: Django>=1.8,<1.9
dj19: Django>=1.9,<1.10
+ dj110: Django>=1.10,<1.11
+ dj111: Django>=1.11,<1.12
commands =
{envpython} setup.py test