Feature/install (#193)

* add yarn

* spirit startproject command

* readme usage

* remove example from travis

* readme run tests

* exit instead of raise

* remove yarn.lock

* core.conf settings

* django.conf.settings -> core.conf.settings everywhere

* editorconfig makefiles

* docs

* core.conf.defaults docs

* installation docs

* upgrade docs

* update history

* spirit.settings deprecation warning

* update readme
This commit is contained in:
Esteban Castro Borsani 2017-09-24 12:38:54 -03:00 committed by GitHub
parent c2f9ed3a49
commit 6dc6c87a04
92 changed files with 919 additions and 291 deletions

View File

@ -24,3 +24,8 @@ indent_size = 2
[*.scss]
indent_style = space
indent_size = 2
# Override for Makefile
[{Makefile, makefile, GNUmakefile}]
indent_style = tab
indent_size = 4

1
.gitignore vendored
View File

@ -22,7 +22,6 @@ __pycache__/
# Distribution / packaging
.Python
env/
bin/
build/
develop-eggs/
dist/

View File

@ -18,7 +18,8 @@ install:
- pip install coveralls pep8==1.5.7 flake8
script:
- flake8 --exit-zero
- ./runtests.py example
- python setup.py build
- python ./spirit/extra/bin/spirit.py startproject project
- coverage run --source=. runtests.py
after_success:
- coveralls

View File

@ -11,6 +11,7 @@
* Remove deprecated `topic_poll` app
* Remove deprecated (since v0.2) `spirit_user.User` (PR #141),
read the wiki or the PR for a workaround
* Deprecates `spirit.settings`. It will be removed in future releases
0.4.8
==================

View File

@ -6,9 +6,6 @@ include requirements.txt
graft spirit
prune example
prune spirit/search/whoosh_index
global-exclude __pycache__
global-exclude *.py[co]
global-exclude .git*

View File

@ -1,5 +1,8 @@
clean:
rm -fr dist/ *.egg-info/
rm -fr dist/ build/ *.egg-info/
docs:
cd docs && make clean && make html
test:
python runtests.py
@ -10,4 +13,4 @@ sdist: test clean
release: test clean
python setup.py sdist upload
.PHONY: clean test sdist release
.PHONY: clean test sdist release docs

View File

@ -15,20 +15,30 @@ To see it in action, please visit [The Spirit Project](http://spirit-project.com
* Django 1.8 LTS (recommended), 1.9 and 1.10
* PostgreSQL (recommended), MySQL, Oracle Database and SQLite
## Installing (Advanced)
## Usage
Check out the [example project](https://github.com/nitely/Spirit/tree/master/example).
```python
pip install django-spirit
spirit startproject mysite
cd mysite
python manage.py spiritinstall
python manage.py createsuperuser
python manage.py runserver
```
## Upgrading
Visit [http://127.0.0.1:8000](http://127.0.0.1:8000)
Detailed upgrade instructions are listed in [Upgrading Spirit](https://github.com/nitely/Spirit/wiki/Upgrading)
For detailed installation and setup docs, see [spirit.readthedocs.io](http://spirit.readthedocs.io/en/latest/)
## Documentation
Docs can be found at [spirit.readthedocs.io](http://spirit.readthedocs.io/en/latest/)
## Testing
The `runtests.py` script enable you to run the test suite of spirit.
- Type `./runtests.py` to run the test suite using the settings from the `spirit` folder.
- Type `./runtests.py example` to run the test suite using the settings from the `example` folder.
```python
$ python runtests.py
```
## License

20
docs/Makefile Normal file
View File

@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = python -msphinx
SPHINXPROJ = Spirit
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

4
docs/changelog.rst Normal file
View File

@ -0,0 +1,4 @@
Changelog
*********
.. include:: ../HISTORY.md

167
docs/conf.py Normal file
View File

@ -0,0 +1,167 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Spirit documentation build configuration file, created by
# sphinx-quickstart on Sun Sep 24 08:30:18 2017.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
import sys
sys.path.insert(0, os.path.abspath('..'))
add_module_names = False
version = __import__('spirit').__version__
release = version
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ['sphinx.ext.autodoc',
'sphinx.ext.githubpages']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = 'Spirit'
copyright = '2017, Esteban Castro Borsani'
author = 'Esteban Castro Borsani'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'alabaster'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
# html_theme_options = {}
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
#
# This is required for the alabaster theme
# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
html_sidebars = {
'**': [
'about.html',
'navigation.html',
'relations.html', # needs 'show_related': True theme option to display
'searchbox.html',
'donate.html',
]
}
# -- Options for HTMLHelp output ------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = 'Spiritdoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'Spirit.tex', 'Spirit Documentation',
'Esteban Castro Borsani', 'manual'),
]
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'spirit', 'Spirit Documentation',
[author], 1)
]
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'Spirit', 'Spirit Documentation',
author, 'Spirit', 'One line description of project.',
'Miscellaneous'),
]

4
docs/contributors.rst Normal file
View File

@ -0,0 +1,4 @@
Contributors
************
.. include:: ../AUTHORS.md

27
docs/index.rst Normal file
View File

@ -0,0 +1,27 @@
.. Spirit documentation master file, created by
sphinx-quickstart on Sun Sep 24 08:30:18 2017.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Spirit's docs
=============
Users Guide
------------
.. toctree::
:maxdepth: 2
installation
upgrade
settings
Additional Notes
----------------
.. toctree::
:maxdepth: 2
contributors
changelog
license

55
docs/installation.rst Normal file
View File

@ -0,0 +1,55 @@
.. _installation:
Installation
============
Compatibility
-------------
* Python 2.7, 3.4 and 3.5 (recommended)
* Django 1.8 LTS (recommended), 1.9 and 1.10
* PostgreSQL (recommended), MySQL, Oracle Database and SQLite
Get started
-----------
Latest version can be installed through pip::
1. Install Spirit::
pip install django-spirit
2. Start your site::
spirit startproject mysite
3. Set up the database::
cd mysite
python manage.py spiritinstall
4. Create an administrator account::
python manage.py createsuperuser
python manage.py runserver
Now sign in at http://127.0.0.1:8000/
Side notes
----------
This will run using the `developer` settings.
Running a production site is out of the scope
of this documentation. However there are many
guides about running a Django site out there.
Here are some hints:
* On production, create a ``prod_local.py``,
import the production settings ``from .prod import *``
and override settings such as ``DATABASES`` and ``ALLOWED_HOSTS``.
* Gunicorn and Nginx are a common way of running Python sites.
* An email server is required. There are self-hosted ones (ie: `exim <http://www.exim.org/>`_),
and managed ones (ie: `Postmark <https://postmarkapp.com/>`_).
* A search engine is required. `Woosh <https://bitbucket.org/mchaput/whoosh/wiki/Home>`_
comes configured by default, however is quite slow. A better choice may be elastic-search.

4
docs/license.rst Normal file
View File

@ -0,0 +1,4 @@
License
=======
.. include:: ../LICENSE

36
docs/make.bat Normal file
View File

@ -0,0 +1,36 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=python -msphinx
)
set SOURCEDIR=.
set BUILDDIR=_build
set SPHINXPROJ=Spirit
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The Sphinx module was not found. Make sure you have Sphinx installed,
echo.then set the SPHINXBUILD environment variable to point to the full
echo.path of the 'sphinx-build' executable. Alternatively you may add the
echo.Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
:end
popd

8
docs/settings.rst Normal file
View File

@ -0,0 +1,8 @@
.. _settings:
Settings
========
.. automodule:: spirit.core.conf.defaults
:members:

36
docs/upgrade.rst Normal file
View File

@ -0,0 +1,36 @@
.. _upgrade:
Upgrade
=======
.. Note::
Upgrade steps for older versions can be found at the
`Wiki <https://github.com/nitely/Spirit/wiki/Upgrading>`_
.. Warning::
Make a database backup before upgrading to avoid data loss,
you have been warned. Use the ``pg_dump`` command on PostgreSQL or
``mysqldump`` on MySQL. You can also create a backup running python
``python manage.py dumpdata --indent=4 > database.json``.
You may want to backup the media folder as well.
.. Note::
Make sure to check the changelog for every
patch version of the upgrading target and
make changes accordingly
From v0.4.x to v0.5.x
---------------------
Starting from spirit v0.5, cloning the repo is no longer encouraged. Pip it instead.
Installation::
pip install -I django-spirit==0.5.x
# Replace the x by the latest patch version
Migration::
python manage.py spiritupgrade
# this will run ``migrate``, ``rebuild_index`` and ``collectstatic``

View File

@ -1,35 +0,0 @@
#Running the example application
Assuming you use virtualenv, follow these steps to download and run the
Spirit example application in this directory:
$ git clone https://github.com/nitely/Spirit.git
$ cd Spirit
$ virtualenv venv
$ source ./venv/bin/activate
$ pip install .
$ cd example
$ python manage.py spiritinstall
$ python manage.py runserver
Visit http://127.0.0.1:8000/
> This will run using the *developer* settings,
> which are not suitable for production environments.
> On production, you should create a `prod_local.py`,
> import the production settings `from .prod import *`
> and overwrite settings such as `SECRET_KEY`, `DATABASES` and `ALLOWED_HOSTS`.
>
> You should run Spirit on a real web server. ie: gunicorn + Nginx.
> An email server is required, you can host your own (ie: [exim](http://www.exim.org/)),
> or hire an external service provider (ie: [Mandrill](http://mandrill.com/)).
> You will need to setup a search engine,
> Spirit is configured to work with [Woosh](https://bitbucket.org/mchaput/whoosh/wiki/Home) by default.

View File

@ -1 +0,0 @@
__author__ = 'Admin'

View File

@ -1,116 +0,0 @@
# -*- coding: utf-8 -*-
"""
Django settings for running the example of spirit app
"""
from __future__ import unicode_literals
import os
import sys
from spirit.settings import *
# You may override or extend spirit settings below...
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
# Quick-start development settings - unsuitable for production
# Application definition
# This will be the default in next version
ST_RATELIMIT_CACHE = 'st_rate_limit'
# Extend the Spirit installed apps.
# Check out the spirit.settings.py so you do not end up with duplicated apps.
INSTALLED_APPS.extend([
# 'my_app1',
# 'my_app2',
])
# same here, check out the spirit.settings.py
MIDDLEWARE_CLASSES.extend([
# 'my_middleware1',
# 'my_middleware2',
])
# same here
TEMPLATES[0]['OPTIONS']['context_processors'].extend([
# 'my_template_proc1',
# 'my_template_proc2',
])
# same here (we update the Spirit caches)
CACHES.update({
# 'default': {
# 'BACKEND': 'my.backend.path',
# },
})
ROOT_URLCONF = 'project.urls'
WSGI_APPLICATION = 'project.wsgi.application'
# Internationalization
# https://docs.djangoproject.com/en/1.6/topics/i18n/
LANGUAGE_CODE = 'en'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.6/howto/static-files/
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
# Send an email to the site admins
# on error when DEBUG=False,
# log to console on error always.
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'filters': {
'require_debug_false': {
'()': 'django.utils.log.RequireDebugFalse'
}
},
'handlers': {
'mail_admins': {
'class': 'django.utils.log.AdminEmailHandler',
'filters': ['require_debug_false'],
},
'console': {
'class': 'logging.StreamHandler',
},
'file': {
'class': 'logging.FileHandler',
'filename': os.path.join(BASE_DIR, 'django.log'),
},
},
'loggers': {
'': {
'handlers': ['console', 'mail_admins'],
'level': 'ERROR',
'propagate': False,
},
'django': {
'handlers': ['console', 'mail_admins'],
'level': 'ERROR',
'propagate': False,
},
}
}

View File

@ -1,34 +0,0 @@
# -*- coding: utf-8 -*-
# THIS IS FOR DEVELOPMENT ENVIRONMENT
# DO NOT USE IT IN PRODUCTION
# This is used to test settings and urls from example directory
# with `./runtests.py example`
from __future__ import unicode_literals
from .base import *
SECRET_KEY = "TEST"
INSTALLED_APPS.extend([
'spirit.core.tests',
])
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db_test.sqlite3'),
}
}
ROOT_URLCONF = 'example.project.urls'
PASSWORD_HASHERS = [
'django.contrib.auth.hashers.MD5PasswordHasher',
]
MEDIA_ROOT = os.path.join(BASE_DIR, 'media_test')
STATIC_ROOT = os.path.join(BASE_DIR, 'static_test')

View File

@ -1,5 +0,0 @@
# -*- coding: utf-8 -*-
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

View File

@ -11,14 +11,7 @@ import django
from django.test.runner import DiscoverRunner
EXAMPLE = 'example' in sys.argv
if EXAMPLE:
# Run tests with example settings
os.environ['DJANGO_SETTINGS_MODULE'] = 'example.project.settings.test' # pragma: no cover
else:
# Run tests with tests settings
os.environ['DJANGO_SETTINGS_MODULE'] = 'spirit.settings_tests'
os.environ['DJANGO_SETTINGS_MODULE'] = 'project.project.settings.test'
def log_warnings():
@ -28,8 +21,9 @@ def log_warnings():
def run_tests():
sys.stdout.write("\nRunning spirit test suite, using settings %(settings)r\n\n"
% {"settings": os.environ['DJANGO_SETTINGS_MODULE'], })
sys.stdout.write(
"\nRunning spirit test suite, using settings %(settings)r\n\n" %
{"settings": os.environ['DJANGO_SETTINGS_MODULE']})
test_runner = DiscoverRunner()
failures = test_runner.run_tests([])
sys.exit(failures)

View File

@ -31,6 +31,10 @@ setup(
url='http://spirit-project.com/',
packages=find_packages(),
test_suite="runtests.start",
entry_points="""
[console_scripts]
spirit=spirit.extra.bin.spirit:main
""",
include_package_data=True,
zip_safe=False,
install_requires=REQUIREMENTS,

View File

@ -2,10 +2,11 @@
from __future__ import unicode_literals
from django.db import models, migrations
from django.conf import settings
def default_categories(apps, schema_editor):
from ...core.conf import settings
Category = apps.get_model("spirit_category", "Category")
if not Category.objects.filter(pk=settings.ST_TOPIC_PRIVATE_CATEGORY_PK).exists():

View File

@ -5,11 +5,11 @@ from __future__ import unicode_literals
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.core.urlresolvers import reverse
from django.conf import settings
from django.utils import timezone
from .managers import CategoryQuerySet
from ..core.conf import settings
from ..core.utils.models import AutoSlugField
from .managers import CategoryQuerySet
class Category(models.Model):

View File

@ -7,10 +7,10 @@ import datetime
from django.test import TestCase
from django.core.urlresolvers import reverse
from django.utils import timezone
from django.conf import settings
from djconfig.utils import override_djconfig
from ..core.conf import settings
from ..core.tests import utils
from ..topic.models import Topic
from ..comment.bookmark.models import CommentBookmark

View File

@ -4,10 +4,10 @@ from __future__ import unicode_literals
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
from djconfig import config
from ...core.conf import settings
from ...core.utils import paginator

View File

@ -4,9 +4,10 @@ from __future__ import unicode_literals
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
from django.utils import timezone
from ...core.conf import settings
REASON_CHOICES = (
(0, _("Spam")),

View File

@ -8,12 +8,12 @@ import logging
import magic
from django import forms
from django.conf import settings
from django.core.files.storage import default_storage
from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import smart_bytes
from django.core.files.uploadedfile import TemporaryUploadedFile
from ..core.conf import settings
from ..core import utils
from ..core.utils.markdown import Markdown
from ..topic.models import Topic

View File

@ -3,11 +3,12 @@
from __future__ import unicode_literals
from django.db import models
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from django.core.urlresolvers import reverse
from django.utils import timezone
from ...core.conf import settings
class CommentLike(models.Model):

View File

@ -5,10 +5,10 @@ from __future__ import unicode_literals
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.core.urlresolvers import reverse
from django.conf import settings
from django.db.models import F
from django.utils import timezone
from ..core.conf import settings
from .managers import CommentQuerySet

View File

@ -4,13 +4,16 @@ from __future__ import unicode_literals, division
from django.db import models, transaction
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
from django.utils import timezone
from django.utils.functional import cached_property
from django.db.models import F
from ...core.conf import settings
from ...core.utils import get_query_string
from .managers import CommentPollQuerySet, CommentPollChoiceQuerySet, CommentPollVoteQuerySet
from .managers import (
CommentPollQuerySet,
CommentPollChoiceQuerySet,
CommentPollVoteQuerySet)
class PollMode(object):

View File

@ -4,8 +4,8 @@ from __future__ import unicode_literals
from django.utils.translation import ugettext_lazy as _
from django.utils.html import mark_safe
from django.conf import settings
from ..core.conf import settings
from ..core.tags.registry import register
from .poll.utils.render import render_polls
from .forms import CommentForm

View File

@ -12,11 +12,11 @@ from django.core.urlresolvers import reverse
from django.template import Template, Context
from django.core.exceptions import PermissionDenied
from django.contrib.auth import get_user_model
from django.conf import settings
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test.utils import override_settings
from django.utils.six import BytesIO
from ..core.conf import settings
from ..core.tests import utils
from .models import Comment
from .forms import CommentForm, CommentMoveForm, CommentImageForm

View File

@ -3,8 +3,8 @@
from __future__ import unicode_literals
from django.conf.urls import url, include
from django.conf import settings
from ..core.conf import settings
import spirit.comment.bookmark.urls
import spirit.comment.flag.urls
import spirit.comment.history.urls

View File

@ -2,7 +2,6 @@
from __future__ import unicode_literals
from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect, get_object_or_404
from django.views.decorators.http import require_POST

View File

@ -0,0 +1,7 @@
# -*- coding: utf-8 -*-
from .settings import settings
__all__ = [
'settings'
]

View File

@ -0,0 +1,102 @@
# -*- coding: utf-8 -*-
"""
These are the default settings. \
They can be overridden by the project settings
"""
from __future__ import unicode_literals
import os
#: The category's PK containing all of the private topics.
#: The category is auto-created and so this value should not change
ST_TOPIC_PRIVATE_CATEGORY_PK = 1
#: Enable/disable the rate-limit for all forms
ST_RATELIMIT_ENABLE = True
#: The cache key prefix. This is mostly to avoid clashing with other apps
ST_RATELIMIT_CACHE_PREFIX = 'srl'
#: The cache ID for storing rate-limit related data.
#: The cache ID must be a valid ``CACHES`` entry and
#: the ``TIMEOUT`` must be ``None`` otherwise it will misbehave
ST_RATELIMIT_CACHE = 'st_rate_limit'
#: A warning will be printed when the ``TIMEOUT``
#: is not ``None``. Setting this to ``True`` will silence it.
#:
#: .. Warning:: A ``ConfigurationError`` will be raised instead of a warning in Spirit > 0.5
ST_RATELIMIT_SKIP_TIMEOUT_CHECK = False
#: Number of notifications per page
ST_NOTIFICATIONS_PER_PAGE = 20
#: Maximum length for a comment
ST_COMMENT_MAX_LEN = 3000
#: Maximum number of mentions per comment willing to process
ST_MENTIONS_PER_COMMENT = 30
#: Minutes to wait before a given user
#: will be able to post a duplicated comment/topic
ST_DOUBLE_POST_THRESHOLD_MINUTES = 30
#: Number of next/previous pages the paginator will show
ST_YT_PAGINATOR_PAGE_RANGE = 3
#: Minimum length for a given search query
ST_SEARCH_QUERY_MIN_LEN = 3
#: Threshold in minutes before the user
#: `"last seen"` info can be updated
ST_USER_LAST_SEEN_THRESHOLD_MINUTES = 1
#: Settings this to ``True`` will require
#: all users to be logged-in to access any section
ST_PRIVATE_FORUM = False
#: Enable/disable image uploads within posts
ST_UPLOAD_IMAGE_ENABLED = True
#: Uploaded images will be validated against these formats.
#: Also, the file choosing dialog will filter by these extensions.
#: See the `Pillow docs <http://pillow.readthedocs.io/en/latest/handbook/image-file-formats.html>`_
#: for a list of supported formats
#:
#: .. Warning::
#: Allowing PNG files is a security risk as it may contain malicious HTML.
#: See `Django notes <https://docs.djangoproject.com/en/1.11/topics/security/#user-uploaded-content>`_
ST_ALLOWED_UPLOAD_IMAGE_FORMAT = ('jpeg', 'jpg', 'gif')
#: Enable/disable file uploads within posts
ST_UPLOAD_FILE_ENABLED = True
#: Uploaded files will be validated against these formats.
#: This is a map of extension and media-type. Both are used for validation.
#:
#: .. Note::
#: To find a media-type just add an extension and an empty media-type,
#: then try uploading a valid file for that extension and the expected
#: media-type will be printed within the validation error.
#: Either that or use the Linux ``file --mime-type ./my_file`` command
ST_ALLOWED_UPLOAD_FILE_MEDIA_TYPE = {
'doc': 'application/msword',
'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'pdf': 'application/pdf'}
#: Link protocols allowed within posts
ST_ALLOWED_URL_PROTOCOLS = {
'http', 'https', 'mailto', 'ftp', 'ftps',
'git', 'svn', 'magnet', 'irc', 'ircs'}
#: Support unicode slugs. Set to ``False``
#: to only allow ASCII chars
ST_UNICODE_SLUGS = True
#: Reject duplicated emails when creating a new account
ST_UNIQUE_EMAILS = True
#: Make emails case insensitive
ST_CASE_INSENSITIVE_EMAILS = True
# Tests helper
ST_TESTS_RATELIMIT_NEVER_EXPIRE = False
# Full route to the spirit package
ST_BASE_DIR = (
os.path.dirname(
os.path.dirname(
os.path.dirname(__file__))))

View File

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
from django.conf import settings as django_settings
from . import defaults
__all__ = ['settings']
class Settings:
"""
Get a setting from django settings or\
Spirit's defaults. In that order
"""
def __getattr__(self, item):
try:
return getattr(django_settings, item)
except AttributeError:
return getattr(defaults, item)
settings = Settings()

View File

@ -5,8 +5,8 @@ import os
from django.core.management.base import BaseCommand, CommandError
from django.core.management import call_command
from django.conf import settings
from ...conf import settings
from ... import utils

View File

@ -5,8 +5,8 @@ from subprocess import call
import os
from django.core.management.base import BaseCommand, CommandError
from django.conf import settings
from ...conf import settings
from ... import utils

View File

@ -5,8 +5,8 @@ from subprocess import call
import os
from django.core.management.base import BaseCommand, CommandError
from django.conf import settings
from ...conf import settings
from ... import utils

View File

@ -2,7 +2,6 @@
from __future__ import unicode_literals
from django.conf import settings
from django.contrib.auth.views import redirect_to_login
from django.core.urlresolvers import resolve
@ -11,6 +10,8 @@ try:
except ImportError: # Django < 1.10
MiddlewareMixin = object
from .conf import settings
class XForwardedForMiddleware(MiddlewareMixin):

View File

@ -2,7 +2,7 @@
from __future__ import unicode_literals
from django.conf import settings as django_settings
from ..conf import settings as st_settings
from .registry import register
@ -10,6 +10,6 @@ from .registry import register
@register.simple_tag(takes_context=True)
def load_settings(context, *settings):
context['st_settings'] = {
setting: getattr(django_settings, setting)
setting: getattr(st_settings, setting)
for setting in settings}
return ''

View File

@ -2,7 +2,7 @@
from __future__ import unicode_literals
from django.conf import settings
from .conf import settings
try:
# TODO: remove this try block.

View File

@ -14,13 +14,13 @@ from django.utils import timezone
from django.contrib.auth.models import AnonymousUser
from django.http import HttpResponseRedirect
from django.http import HttpResponse
from django.conf import settings
from django.core.exceptions import PermissionDenied
from django.contrib import messages
from django.utils.timezone import utc
from django.utils.http import urlunquote
from django.contrib.auth import get_user_model
from ..conf import settings
from ...category.models import Category
from .. import utils
from ..utils.forms import NestedModelChoiceField

View File

@ -6,13 +6,13 @@ import warnings
from django.test import TestCase, RequestFactory, override_settings
from django.contrib.auth.models import AnonymousUser, User
from django.contrib.messages.storage.fallback import FallbackStorage
from django.conf import settings
from django.core.cache import caches
from . import utils
from ..utils.ratelimit import ratelimit as rl_module
from ..utils.ratelimit import RateLimit
from ..utils.ratelimit.decorators import ratelimit
from ..conf import settings
def setup_request_factory_messages(req):

View File

@ -3,9 +3,9 @@
from __future__ import unicode_literals
from django.contrib.auth import get_user_model
from django.conf import settings
from django.core.cache import caches, cache
from ...core.conf import settings
from ...topic.models import Topic
from ...category.models import Category
from ...comment.models import Comment

View File

@ -6,7 +6,8 @@ from functools import wraps
from django.core.exceptions import PermissionDenied
from django.contrib.auth.views import redirect_to_login
from django.shortcuts import redirect
from django.conf import settings
from ..conf import settings
def moderator_required(view_func):

View File

@ -4,11 +4,11 @@ from __future__ import unicode_literals
import re
import copy
from django.conf import settings
from django.contrib.auth import get_user_model
import mistune
from ...conf import settings
from .utils.emoji import emojis
User = get_user_model()

View File

@ -4,9 +4,10 @@ from __future__ import unicode_literals
import mistune
from django.conf import settings
from django.utils.html import escape
from ...conf import settings
def sanitize_url(url):
url = escape(url) # & -> &amp; ...

View File

@ -4,9 +4,10 @@ from __future__ import unicode_literals
import re
from django.utils.translation import ugettext as _
from django.conf import settings
from django.utils import translation
from ....conf import settings
_PATTERN_POLL = re.compile(
r'^(?:\[poll[^\]]*\])\n+'

View File

@ -7,7 +7,8 @@ from slugify import slugify as unicode_slugify
from django.db.models.fields import SlugField
from django.utils.encoding import smart_text
from django.utils.text import slugify
from django.conf import settings
from ..conf import settings
__all__ = ['AutoSlugField', ]

View File

@ -3,7 +3,8 @@
from __future__ import unicode_literals
from django.core.paginator import InvalidPage
from django.conf import settings
from ...conf import settings
class YTPaginator(object):

View File

@ -5,9 +5,9 @@ from __future__ import unicode_literals
import hashlib
import time
from django.conf import settings
from django.core.cache import caches
from ...conf import settings
from ..deprecations import warn

2
spirit/extra/__init__.py Normal file
View File

@ -0,0 +1,2 @@
# -*- coding: utf-8 -*-

View File

@ -0,0 +1,68 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import unicode_literals, absolute_import, print_function
import os
import functools
import argparse
from importlib import import_module
from subprocess import call
def create_project(project_name, path, exit_err):
try:
import_module(project_name)
except ImportError:
pass
else:
exit_err(
"'%s' conflicts with the name of an existing "
"Python module and cannot be used as a project "
"name" % project_name)
extra_path = os.path.dirname(os.path.dirname(__file__))
template_path = os.path.join(extra_path, 'project_template')
command = [
'django-admin',
'startproject',
'--template=' + template_path,
project_name]
if path:
command.append(path)
print('Creating spirit project...')
if call(command) != 0:
exit_err(
"Tried to run \"%s\" but it "
"returned an error "
"(should be printed above)\n" % ' '.join(command))
print('ok')
def execute_from_command_line():
parser = argparse.ArgumentParser(description='Spirit commands')
subparsers = parser.add_subparsers(help='sub-command help')
start_parser = subparsers.add_parser(
'startproject', help='creates a Spirit project directory structure')
start_parser.add_argument(
'project_name', help='name of the project')
start_parser.add_argument(
'--path', default=None, help='optional destination directory')
args = parser.parse_args()
create_project(
project_name=args.project_name,
path=args.path,
exit_err=functools.partial(parser.exit, 1))
def main():
execute_from_command_line()
if __name__ == "__main__":
main()

View File

@ -0,0 +1,2 @@
# -*- coding: utf-8 -*-

View File

@ -4,7 +4,7 @@ import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings.dev")
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings.dev")
from django.core.management import execute_from_command_line

View File

@ -0,0 +1,194 @@
# -*- coding: utf-8 -*-
"""
Django settings for {{ project_name }} project.
Generated by 'django-admin startproject' using Django {{ django_version }}.
For more information on this file, see
https://docs.djangoproject.com/en/{{ docs_version }}/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/{{ docs_version }}/ref/settings/
"""
from __future__ import unicode_literals
import os
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/{{ docs_version }}/howto/deployment/checklist/
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'spirit.core',
'spirit.admin',
'spirit.search',
'spirit.user',
'spirit.user.admin',
'spirit.user.auth',
'spirit.category',
'spirit.category.admin',
'spirit.topic',
'spirit.topic.admin',
'spirit.topic.favorite',
'spirit.topic.moderate',
'spirit.topic.notification',
'spirit.topic.poll', # todo: remove in Spirit v0.6
'spirit.topic.private',
'spirit.topic.unread',
'spirit.comment',
'spirit.comment.bookmark',
'spirit.comment.flag',
'spirit.comment.flag.admin',
'spirit.comment.history',
'spirit.comment.like',
'spirit.comment.poll',
'djconfig',
'haystack',
]
MIDDLEWARE_CLASSES = [
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
# 'spirit.core.middleware.XForwardedForMiddleware',
'spirit.user.middleware.TimezoneMiddleware',
'spirit.user.middleware.LastIPMiddleware',
'spirit.user.middleware.LastSeenMiddleware',
'spirit.user.middleware.ActiveUserMiddleware',
'spirit.core.middleware.PrivateForumMiddleware',
'djconfig.middleware.DjConfigMiddleware',
]
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'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.template.context_processors.request',
'django.contrib.messages.context_processors.messages',
'djconfig.context_processors.config',
],
},
},
]
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
'LOCATION': 'spirit_cache',
},
'st_rate_limit': {
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
'LOCATION': 'spirit_rl_cache',
'TIMEOUT': None
}
}
AUTHENTICATION_BACKENDS = [
'spirit.user.auth.backends.UsernameAuthBackend',
'spirit.user.auth.backends.EmailAuthBackend',
]
HAYSTACK_CONNECTIONS = {
'default': {
'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
'PATH': os.path.join(BASE_DIR, 'st_search'),
},
}
ROOT_URLCONF = '{{ project_name }}.urls'
WSGI_APPLICATION = '{{ project_name }}.wsgi.application'
LOGIN_URL = 'spirit:user:auth:login'
LOGIN_REDIRECT_URL = 'spirit:user:update'
# Internationalization
# https://docs.djangoproject.com/en/{{ docs_version }}/topics/i18n/
LANGUAGE_CODE = 'en'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/{{ docs_version }}/howto/static-files/
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
# Send an email to the site admins
# on error when DEBUG=False,
# log to console on error always.
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'filters': {
'require_debug_false': {
'()': 'django.utils.log.RequireDebugFalse'
}
},
'handlers': {
'mail_admins': {
'class': 'django.utils.log.AdminEmailHandler',
'filters': ['require_debug_false'],
},
'console': {
'class': 'logging.StreamHandler',
},
'file': {
'class': 'logging.FileHandler',
'filename': os.path.join(BASE_DIR, 'django.log'),
},
},
'loggers': {
'': {
'handlers': ['console', 'mail_admins'],
'level': 'ERROR',
'propagate': False,
},
'django': {
'handlers': ['console', 'mail_admins'],
'level': 'ERROR',
'propagate': False,
},
}
}

View File

@ -5,7 +5,7 @@
# Create your own dev_local.py
# import * this module there and use it like this:
# python manage.py runserver --settings=project.settings.dev_local
# python manage.py runserver --settings={{ project_name }}.settings.dev_local
from __future__ import unicode_literals
@ -15,7 +15,7 @@ from .base import *
DEBUG = True
TEMPLATES[0]['OPTIONS']['debug'] = True
# TEMPLATES[0]['OPTIONS']['string_if_invalid'] = '{{ %s }}' # Some Django templates relies on this being the default
# TEMPLATES[0]['OPTIONS']['string_if_invalid'] = '\{\{%s\}\}' # Some Django templates relies on this being the default
ADMINS = (('John', 'john@example.com'), ) # Log email to console when DEBUG = False
@ -27,6 +27,9 @@ ALLOWED_HOSTS = ['127.0.0.1', ]
# 'debug_toolbar',
# ])
# Database
# https://docs.djangoproject.com/en/{{ docs_version }}/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',

View File

@ -4,23 +4,22 @@
# Create your own prod_local.py
# import * this module there and use it like this:
# python manage.py runserver --settings=project.settings.prod_local
# python manage.py runserver --settings={{ project_name }}.settings.prod_local
from __future__ import unicode_literals
from .base import *
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False
# https://docs.djangoproject.com/en/dev/ref/settings/#admins
# https://docs.djangoproject.com/en/{{ docs_version }}/ref/settings/#admins
ADMINS = (('John', 'john@example.com'), )
# Secret key generator: https://djskgen.herokuapp.com/
# You should set your key as an environ variable
SECRET_KEY = os.environ.get("SECRET_KEY", "")
SECRET_KEY = os.environ.get("SECRET_KEY", '{{ secret_key }}')
# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
# https://docs.djangoproject.com/en/{{ docs_version }}/ref/settings/#allowed-hosts
ALLOWED_HOSTS = ['.example.com', ]
# You can change this to something like 'MyForum <noreply@example.com>'
@ -36,7 +35,9 @@ INSTALLED_APPS.extend([
# 'my_app1',
])
# https://docs.djangoproject.com/en/dev/ref/settings/#databases
# Database
# https://docs.djangoproject.com/en/{{ docs_version }}/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
@ -45,9 +46,6 @@ DATABASES = {
'PASSWORD': 'mypassword',
'HOST': '127.0.0.1',
'PORT': '5432',
# Django default is 0,
# close after every request
# 'CONN_MAX_AGE': 0, # todo: Spirit v0.5 change to Keep alive 60 secs, uncomment
}
}

View File

@ -1,15 +1,13 @@
# -*- coding: utf-8 -*-
"""
Django settings for running the tests of spirit app
"""
from __future__ import unicode_literals
import os
from .base import *
from spirit.settings import *
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
SECRET_KEY = 'TEST'

View File

@ -15,12 +15,12 @@ admin.site.login = login_required(admin.site.login)
urlpatterns = [
url(r'^', include(spirit.urls)),
# Examples:
# url(r'^$', 'example.views.home', name='home'),
# url(r'^example/', include('example.foo.urls')),
url(r'^', include(spirit.urls)),
# Uncomment the admin/doc line below to enable admin documentation:
# url(r'^admin/doc/', include('django.contrib.admindocs.urls')),

View File

@ -0,0 +1,12 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings.dev")
application = get_wsgi_application()

View File

@ -3,13 +3,13 @@
from __future__ import unicode_literals
from django import forms
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import smart_text
from haystack.forms import SearchForm
from haystack.query import EmptySearchQuerySet
from ..core.conf import settings
from ..topic.models import Topic
from ..category.models import Category

View File

@ -2,11 +2,11 @@
from __future__ import unicode_literals
from django.conf import settings
from django.db.models import Q
from haystack import indexes
from ..core.conf import settings
from ..topic.models import Topic

View File

@ -6,7 +6,6 @@ import datetime
from django.test import TestCase, override_settings
from django.core.urlresolvers import reverse
from django.template import Template, Context
from django.conf import settings
from django.core.management import call_command
from django.template.loader import render_to_string
from django.utils import timezone
@ -14,6 +13,7 @@ from django.utils import timezone
from haystack.query import SearchQuerySet
from djconfig.utils import override_djconfig
from ..core.conf import settings
from ..core.tests import utils
from ..topic.models import Topic
from .forms import BasicSearchForm, AdvancedSearchForm

View File

@ -7,6 +7,25 @@ from __future__ import unicode_literals
import os
from collections import OrderedDict
# TODO: Remove this whole module in Spirit 0.6
import warnings
class RemovedInNextVersionWarning2(DeprecationWarning):
""""""
warnings.simplefilter("default", RemovedInNextVersionWarning2)
warnings.warn(
"`spirit.settings` is deprecated and it will be removed in Spirit 0.6. "
"You are most likely seeing this because settings.base.py contains "
"`from spirit.settings import *`. "
"The best way to procede is to create a clean project (run "
"`spirit startproject mysite`) and modify the settings as needed. "
"It's a straightforward procedure.",
category=RemovedInNextVersionWarning2,
stacklevel=2)
ST_TOPIC_PRIVATE_CATEGORY_PK = 1
ST_RATELIMIT_ENABLE = True

View File

@ -3,10 +3,11 @@
from __future__ import unicode_literals
from django.db import models
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
from ...core.conf import settings
class TopicFavorite(models.Model):

View File

@ -5,12 +5,12 @@ from __future__ import unicode_literals
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.core.urlresolvers import reverse
from django.conf import settings
from django.utils import timezone
from django.db.models import F
from .managers import TopicQuerySet
from ..core.utils.models import AutoSlugField
from ..core.conf import settings
class Topic(models.Model):

View File

@ -4,11 +4,11 @@ from __future__ import unicode_literals
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
from django.utils import timezone
from django.db import IntegrityError, transaction
from .managers import TopicNotificationQuerySet
from ...core.conf import settings
UNDEFINED, MENTION, COMMENT = range(3)

View File

@ -7,12 +7,12 @@ from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect, get_object_or_404
from django.views.decorators.http import require_POST
from django.http import Http404, HttpResponse
from django.conf import settings
from django.contrib import messages
from django.utils.html import escape
from djconfig import config
from ...core.conf import settings
from ...core import utils
from ...core.utils.paginator import yt_paginate
from ...core.utils.paginator.infinite_paginator import paginate

View File

@ -5,9 +5,9 @@ from __future__ import unicode_literals
from django import forms
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth import get_user_model
from django.conf import settings
from django.utils.encoding import smart_bytes
from ...core.conf import settings
from ...core import utils
from ...core.utils.widgets import MultipleInput
from ...topic.models import Topic

View File

@ -3,11 +3,11 @@
from __future__ import unicode_literals
from django.db import models
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
from .managers import TopicPrivateQuerySet
from ...core.conf import settings
class TopicPrivate(models.Model):

View File

@ -7,11 +7,11 @@ import hashlib
from django.test import TestCase, override_settings
from django.core.urlresolvers import reverse
from django.template import Template, Context
from django.conf import settings
from django.utils import timezone
from djconfig.utils import override_djconfig
from ...core.conf import settings
from ...core.tests import utils
from ...category.models import Category
from .models import TopicPrivate

View File

@ -9,10 +9,10 @@ from django.shortcuts import render, redirect, get_object_or_404
from django.views.decorators.http import require_POST
from django.contrib import messages
from django.http import HttpResponsePermanentRedirect
from django.conf import settings
from djconfig import config
from ...core.conf import settings
from ...core import utils
from ...core.utils.paginator import paginate, yt_paginate
from ...core.utils.ratelimit.decorators import ratelimit

View File

@ -4,9 +4,10 @@ from __future__ import unicode_literals
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
from django.utils import timezone
from ...core.conf import settings
class TopicUnread(models.Model):

View File

@ -5,7 +5,6 @@ from __future__ import unicode_literals
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponsePermanentRedirect
from django.conf import settings
from djconfig import config

View File

@ -4,7 +4,8 @@ from __future__ import unicode_literals
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model
from django.conf import settings
from ...core.conf import settings
User = get_user_model()

View File

@ -6,8 +6,8 @@ from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import AuthenticationForm
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
from ...core.conf import settings
from ..forms import CleanEmailMixin
User = get_user_model()

View File

@ -7,8 +7,8 @@ from django.utils.translation import ugettext_lazy as _
from django.contrib.auth import get_user_model
from django.utils import timezone
from django.template import defaultfilters
from django.conf import settings
from ..core.conf import settings
from ..core.utils.timezone import timezones
from .models import UserProfile

View File

@ -5,7 +5,6 @@ import logging
import pytz
from django.conf import settings
from django.contrib.auth import logout
from django.utils import timezone
@ -14,6 +13,7 @@ try:
except ImportError: # Django < 1.10
MiddlewareMixin = object
from ..core.conf import settings
from .models import UserProfile

View File

@ -2,10 +2,11 @@
from __future__ import unicode_literals
from django.db import models, migrations
from django.conf import settings
def migrate_profiles(apps, schema_editor):
from ...core.conf import settings
User = apps.get_model(settings.AUTH_USER_MODEL)
UserProfile = apps.get_model('spirit_user', 'UserProfile')

View File

@ -24,7 +24,7 @@ class User(AbstractUser):
def user_model_checker(apps, schema_editor):
from django.conf import settings
from ...core.conf import settings
if not hasattr(settings, 'AUTH_USER_MODEL'):
return

View File

@ -6,7 +6,7 @@ from django.db import migrations
def user_model_content_type(apps, schema_editor):
from django.conf import settings
from ...core.conf import settings
if not hasattr(settings, 'AUTH_USER_MODEL'):
return

View File

@ -7,8 +7,8 @@ from django.db import models
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
from django.conf import settings
from ..core.conf import settings
from ..core.utils.models import AutoSlugField

View File

@ -7,11 +7,13 @@ from django.contrib.sites.shortcuts import get_current_site
from django.utils.translation import ugettext as _
from django.template.loader import render_to_string
from django.core.mail import send_mail
from django.conf import settings
from .tokens import UserActivationTokenGenerator, UserEmailChangeTokenGenerator
from ...core.conf import settings
from .tokens import (
UserActivationTokenGenerator,
UserEmailChangeTokenGenerator)
logger = logging.getLogger('django')
logger = logging.getLogger(__name__)
def sender(request, subject, template_name, context, to):