From 0506d8c19c5d99941f33d2f229cdf31b85926959 Mon Sep 17 00:00:00 2001 From: Gert Van Gool Date: Sat, 19 Aug 2017 20:47:06 +0200 Subject: [PATCH 1/7] Adds testing for Python3 --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 11bf405..ce0ec87 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}, py35-dj18, docs [testenv] deps = From 777498eca4afcbc5a8c34c761071e9168498deaf Mon Sep 17 00:00:00 2001 From: Gert Van Gool Date: Sat, 19 Aug 2017 20:51:59 +0200 Subject: [PATCH 2/7] Adds new style and old style urlpatterns together --- fack/urls.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) 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) From be88193ff028183855f934b760107b40a3e6cc25 Mon Sep 17 00:00:00 2001 From: Gert Van Gool Date: Sat, 19 Aug 2017 20:58:49 +0200 Subject: [PATCH 3/7] Support settings.TEMPLATES for Django 1.9 and up --- fack/tests/test_views.py | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) 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) From 10cb3eb0a8a992c9e546bd2d2c9d651e50f15efc Mon Sep 17 00:00:00 2001 From: Gert Van Gool Date: Sat, 19 Aug 2017 20:59:18 +0200 Subject: [PATCH 4/7] Add test running for Django 1.10 and 1.11 --- tox.ini | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index ce0ec87..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}, py35-dj18, 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 From 424ace98d5c50566c232d4c41892c4f556a02e70 Mon Sep 17 00:00:00 2001 From: Gert Van Gool Date: Fri, 3 May 2019 23:15:31 +0200 Subject: [PATCH 5/7] Update the example app based on Django 1.11 Create a new project that can server as a example app. This fixes #12. --- example/manage.py | 33 ++++----- example/settings.py | 136 +++++++++++++++++++++++++++++------- example/templates/home.html | 3 +- example/urls.py | 39 ++++++----- example/wsgi.py | 16 +++++ 5 files changed, 166 insertions(+), 61 deletions(-) create mode 100644 example/wsgi.py 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() From ed7cec6197dbdba45d6e76285c905dc50af300cf Mon Sep 17 00:00:00 2001 From: Gert Van Gool Date: Sat, 4 May 2019 16:28:22 +0200 Subject: [PATCH 6/7] Include templates in generated wheels --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 194fce5..f6392e8 100644 --- a/setup.py +++ b/setup.py @@ -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 = [ From e6e672514d9f4c89b2d411c9917e6fac2542894e Mon Sep 17 00:00:00 2001 From: Gert Van Gool Date: Sat, 4 May 2019 17:57:59 +0200 Subject: [PATCH 7/7] Bump version to 1.2.0 --- fack/__init__.py | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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/setup.py b/setup.py index f6392e8..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",