diff --git a/CHANGELOG.md b/CHANGELOG.md
index c40bb26b..24f8d11c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,10 @@
All enhancements and patches to Cookiecutter Django will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
+## [2018-01-15]
+### Changed
+- Removed Elastic Beanstalk support (@pydanny)
+
## [2017-12-28]
### Changed
- Upgraded to Django 1.11 (@pydanny)
diff --git a/CONTRIBUTORS.rst b/CONTRIBUTORS.rst
index 4cf632db..a9a85773 100644
--- a/CONTRIBUTORS.rst
+++ b/CONTRIBUTORS.rst
@@ -7,17 +7,18 @@ Core Developers
These contributors have commit flags for the repository,
and are able to accept and merge pull requests.
-=========================== ============= ===========
-Name Github Twitter
-=========================== ============= ===========
-Daniel Roy Greenfeld `@pydanny`_ @pydanny
-Audrey Roy Greenfeld* `@audreyr`_ @audreyr
-Fábio C. Barrionuevo da Luz `@luzfcb`_ @luzfcb
-Saurabh Kumar `@theskumar`_ @_theskumar
+=========================== ================ ===========
+Name Github Twitter
+=========================== ================ ===========
+Daniel Roy Greenfeld `@pydanny`_ @pydanny
+Audrey Roy Greenfeld* `@audreyr`_ @audreyr
+Fábio C. Barrionuevo da Luz `@luzfcb`_ @luzfcb
+Saurabh Kumar `@theskumar`_ @_theskumar
Jannis Gebauer `@jayfk`_
-Burhan Khalid `@burhan`_ @burhan
-Shupeyko Nikita `@webyneter`_ @webyneter
-=========================== ============= ===========
+Burhan Khalid `@burhan`_ @burhan
+Shupeyko Nikita `@webyneter`_ @webyneter
+Bruno Alla `@browniebroke`_ @_BrunoAlla
+=========================== ================ ===========
*Audrey is also the creator of Cookiecutter. Audrey and
Daniel are on the Cookiecutter core team.*
@@ -28,6 +29,7 @@ Daniel are on the Cookiecutter core team.*
.. _@audreyr: https://github.com/audreyr
.. _@jayfk: https://github.com/jayfk
.. _@webyneter: https://github.com/webyneter
+.. _@browniebroke: https://github.com/browniebroke
Other Contributors
------------------
@@ -64,7 +66,6 @@ Listed in alphabetical order.
Bo Lopker `@blopker`_
Bouke Haarsma
Brent Payne `@brentpayne`_ @brentpayne
- Bruno Alla `@browniebroke`_ @_BrunoAlla
Burhan Khalid `@burhan`_ @burhan
Catherine Devlin `@catherinedevlin`_
Cédric Gaspoz `@cgaspoz`_
@@ -171,7 +172,6 @@ Listed in alphabetical order.
.. _@bloodpet: https://github.com/bloodpet
.. _@blopker: https://github.com/blopker
.. _@bogdal: https://github.com/bogdal
-.. _@browniebroke: https://github.com/browniebroke
.. _@burhan: https://github.com/burhan
.. _@c-rhodes: https://github.com/c-rhodes
.. _@caffodian: https://github.com/caffodian
@@ -228,7 +228,6 @@ Listed in alphabetical order.
.. _@rm--: https://github.com/rm--
.. _@romanosipenko: https://github.com/romanosipenko
.. _@shireenrao: https://github.com/shireenrao
-.. _@webyneter: https://github.com/webyneter
.. _@show0k: https://github.com/show0k
.. _@sfdye: https://github.com/sfdye
.. _@shultz: https://github.com/shultz
@@ -240,7 +239,7 @@ Listed in alphabetical order.
.. _@timfreund: https://github.com/timfreund
.. _@Travistock: https://github.com/Tavistock
.. _@trungdong: https://github.com/trungdong
-.. _@viviangb: httpsL//github.com/viviangb
+.. _@viviangb: https://github.com/viviangb
.. _@xpostudio4: https://github.com/xpostudio4
.. _@yunti: https://github.com/yunti
.. _@zcho: https://github.com/zcho
@@ -250,6 +249,12 @@ Listed in alphabetical order.
.. _@jangeador: https://github.com/jangeador
.. _@townie: https://github.com/townie
.. _@MightySCollins: https://github.com/MightySCollins
+.. _@dadokkio: https://github.com/dadokkio
+.. _@bwarren2: https://github.com/bwarren2
+.. _@bertdemiranda: https://github.com/bertdemiranda
+.. _@brentpayne: https://github.com/brentpayne
+.. _@afrowave: https://github.com/afrowave
+.. _@pchiquet: https://github.com/pchiquet
Special Thanks
~~~~~~~~~~~~~~
diff --git a/LICENSE b/LICENSE
index 9a5d2fc0..da2bbe30 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2013-2016, Daniel Greenfeld
+Copyright (c) 2013-2018, Daniel Greenfeld
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
diff --git a/README.rst b/README.rst
index 838253f4..6536ab7e 100644
--- a/README.rst
+++ b/README.rst
@@ -12,6 +12,10 @@ Cookiecutter Django
.. image:: https://badges.gitter.im/Join Chat.svg
:target: https://gitter.im/pydanny/cookiecutter-django?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
+.. image:: https://www.codetriage.com/pydanny/cookiecutter-django/badges/users.svg
+ :target: https://www.codetriage.com/pydanny/cookiecutter-django
+ :alt: Code Helpers Badge
+
Powered by Cookiecutter_, Cookiecutter Django is a framework for jumpstarting
production-ready Django projects quickly.
@@ -51,7 +55,6 @@ Features
* Instructions for deploying to PythonAnywhere_
* Run tests with unittest or py.test
* Customizable PostgreSQL version
-* Experimental support for Amazon Elastic Beanstalk
.. _`maintained Foundation fork`: https://github.com/Parbhat/cookiecutter-django-foundation
@@ -168,16 +171,19 @@ Answer the prompts with your own desired options_. For example::
use_heroku [n]: y
use_compressor [n]: y
Select postgresql_version:
- 1 - 9.5
- 2 - 9.4
- 3 - 9.3
- 4 - 9.2
+ 1 - 10
+ 2 - 9.6
+ 3 - 9.5
+ 4 - 9.4
+ 5 - 9.3
+ 6 - 9.2
Choose from 1, 2, 3, 4 [1]: 1
Select js_task_runner:
1 - Gulp
2 - Grunt
3 - None
Choose from 1, 2, 3, 4 [1]: 1
+ custom_bootstrap_compilation [n]: n
Select open_source_license:
1 - MIT
2 - BSD
@@ -185,7 +191,6 @@ Answer the prompts with your own desired options_. For example::
4 - Apache Software License 2.0
5 - Not open source
Choose from 1, 2, 3, 4, 5 [1]: 1
- use_elasticbeanstalk_experimental: n
Enter the project and take a look around::
@@ -222,7 +227,7 @@ Community
.. _`issue`: https://github.com/pydanny/cookiecutter-django/issues
.. _`Gitter`: https://gitter.im/pydanny/cookiecutter-django?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
-For Readers of Two Scoops of Django 1.8
+For Readers of Two Scoops of Django
--------------------------------------------
You may notice that some elements of this project do not exactly match what we describe in chapter 3. The reason for that is this project, amongst other things, serves as a test bed for trying out new ideas and concepts. Sometimes they work, sometimes they don't, but the end result is that it won't necessarily match precisely what is described in the book I co-authored.
@@ -274,14 +279,21 @@ experience better.
Articles
---------
+* `Deploying Cookiecutter-Django with Docker-Compose`_ - Oct. 19, 2017
+* `Using Cookiecutter to Jumpstart a Django Project on Windows with PyCharm`_ - May 19, 2017
+* `Exploring with Cookiecutter`_ - Dec. 3, 2016
+* `Introduction to Cookiecutter-Django`_ - Feb. 19, 2016
+* `Django and GitLab - Running Continuous Integration and tests with your FREE account`_ - May. 11, 2016
* `Development and Deployment of Cookiecutter-Django on Fedora`_ - Jan. 18, 2016
* `Development and Deployment of Cookiecutter-Django via Docker`_ - Dec. 29, 2015
* `How to create a Django Application using Cookiecutter and Django 1.8`_ - Sept. 12, 2015
-* `Introduction to Cookiecutter-Django`_ - Feb. 19, 2016
-* `Django and GitLab - Running Continuous Integration and tests with your FREE account`_ - May. 11, 2016
Have a blog or online publication? Write about your cookiecutter-django tips and tricks, then send us a pull request with the link.
+.. _`Deploying Cookiecutter-Django with Docker-Compose`: http://adamantine.me/2017/10/19/deploying-cookiecutter-django-with-docker-compose/
+.. _`Exploring with Cookiecutter`: http://www.snowboardingcoder.com/django/2016/12/03/exploring-with-cookiecutter/
+.. _`Using Cookiecutter to Jumpstart a Django Project on Windows with PyCharm`: https://joshuahunter.com/posts/using-cookiecutter-to-jumpstart-a-django-project-on-windows-with-pycharm/
+
.. _`Development and Deployment of Cookiecutter-Django via Docker`: https://realpython.com/blog/python/development-and-deployment-of-cookiecutter-django-via-docker/
.. _`Development and Deployment of Cookiecutter-Django on Fedora`: https://realpython.com/blog/python/development-and-deployment-of-cookiecutter-django-on-fedora/
.. _`How to create a Django Application using Cookiecutter and Django 1.8`: https://www.swapps.io/blog/how-to-create-a-django-application-using-cookiecutter-and-django-1-8/
diff --git a/cookiecutter.json b/cookiecutter.json
index 184e8796..933c3dfa 100644
--- a/cookiecutter.json
+++ b/cookiecutter.json
@@ -16,7 +16,6 @@
"windows": "n",
"use_docker": "n",
"use_heroku": "n",
- "use_elasticbeanstalk_experimental": "n",
"use_compressor": "n",
"postgresql_version": ["10", "9.6", "9.5", "9.4", "9.3", "9.2"],
"js_task_runner": ["Gulp", "Grunt", "None"],
diff --git a/docs/deployment-with-elastic-beanstalk.rst b/docs/deployment-with-elastic-beanstalk.rst
deleted file mode 100644
index e8aae885..00000000
--- a/docs/deployment-with-elastic-beanstalk.rst
+++ /dev/null
@@ -1,72 +0,0 @@
-Deployment with Elastic Beanstalk
-==========================================
-
-.. index:: Elastic Beanstalk
-
-Warning: Experimental
----------------------
-
-This is experimental. For the time being there will be bugs and issues. If you've never used Elastic Beanstalk before, please hold off before trying this option.
-
-On the other hand, we need help cleaning this up. If you do have knowledge of Elastic Beanstalk, we would appreciate the help. :)
-
-Prerequisites
--------------
-
-* awsebcli
-
-Instructions
--------------
-
-If you haven't done so, create a directory of environments::
-
- eb init -p python3.4 MY_PROJECT_SLUG
-
-Replace `MY_PROJECT_SLUG` with the value you entered for `project_slug`.
-
-Once that is done, create the environment (server) where the app will run::
-
- eb create MY_PROJECT_SLUG
- # Note: This will eventually fail on a postgres error, because postgres doesn't exist yet
-
-Now make sure you are in the right environment::
-
- eb list
-
-If you are not in the right environment, then put yourself in the correct one::
-
- eb use MY_PROJECT_SLUG
-
-Set the environment variables. Notes: You will be prompted if the `.env` file is missing. The script will ignore any PostgreSQL values, as RDS uses it's own system::
-
- # Set the environment variables
- python ebsetenv.py
-
-Speaking of PostgreSQL, go to the Elasting Beanstalk configuration panel for RDS. Create new RDS database, with these attributes:
-
-* PostgreSQL
-* Version 9.4.9
-* Size db.t2.micro (You can upgrade later)
-
-(Get some coffee, this is going to take a while)
-
-Once you have a database specified, deploy again so your instance can pick up the new PostgreSQL values::
-
- eb deploy
-
-Take a look::
-
- eb open
-
-FAQ
------
-
-Why Not Use Docker on Elastic Beanstalk?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Because I didn't want to add an abstraction (Docker) on top of an abstraction (Elastic Beanstalk) on top of an abstraction (Cookiecutter Django).
-
-Why Can't I Use Both Docker/Heroku with Elastic Beanstalk?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Because the environment variables that our Docker and Heroku setups use for PostgreSQL access is different then how Amazon RDS handles this access. At this time we're just trying to get things to work reliably with Elastic Beanstalk, and full integration will come later.
diff --git a/docs/index.rst b/docs/index.rst
index 3b0a268c..41a1138f 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -25,7 +25,6 @@ Contents:
faq
troubleshooting
my-favorite-cookie
- deployment-with-elastic-beanstalk
Indices and tables
==================
diff --git a/docs/project-generation-options.rst b/docs/project-generation-options.rst
index 5a0cffe6..d1d36324 100644
--- a/docs/project-generation-options.rst
+++ b/docs/project-generation-options.rst
@@ -73,7 +73,9 @@ js_task_runner [1]
3. None
custom_bootstrap_compilation [n]
- If you use Grunt, scaffold out recompiling Bootstrap as as task. (Useful for letting you change Bootstrap variables in real time.) Consult project README for more details.
+ Scaffold out recompiling Bootstrap as as task, with Gulp_ or Grunt_.
+ Useful for letting you change Bootstrap variables in real time.
+ Consult project README for more details.
open_source_license [1]
Select a software license for the project. The choices are:
diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py
index b383e419..9a6da7b6 100644
--- a/hooks/post_gen_project.py
+++ b/hooks/post_gen_project.py
@@ -12,6 +12,7 @@ A portion of this code was adopted from Django's standard crypto functions and
utilities, specifically:
https://github.com/django/django/blob/master/django/utils/crypto.py
"""
+from __future__ import print_function
import os
import random
import shutil
@@ -119,8 +120,6 @@ def remove_heroku_files():
Removes files needed for heroku if it isn't going to be used
"""
filenames = ["Procfile", "runtime.txt"]
- if '{{ cookiecutter.use_elasticbeanstalk_experimental }}'.lower() != 'y':
- filenames.append("requirements.txt")
for filename in ["Procfile", "runtime.txt"]:
file_name = os.path.join(PROJECT_DIRECTORY, filename)
remove_file(file_name)
@@ -131,9 +130,9 @@ def remove_docker_files():
Removes files needed for docker if it isn't going to be used
"""
for filename in ["local.yml", "production.yml", ".dockerignore"]:
- os.remove(os.path.join(
- PROJECT_DIRECTORY, filename
- ))
+ filename = os.path.join(PROJECT_DIRECTORY, filename)
+ if os.path.exists(filename):
+ os.remove(filename)
shutil.rmtree(os.path.join(
PROJECT_DIRECTORY, "compose"
@@ -167,7 +166,6 @@ def remove_packageJSON_file():
PROJECT_DIRECTORY, filename
))
-
def remove_copying_files():
"""
Removes files needed for the GPLv3 licence if it isn't going to be used
@@ -177,31 +175,6 @@ def remove_copying_files():
PROJECT_DIRECTORY, filename
))
-def remove_elasticbeanstalk():
- """
- Removes elastic beanstalk components
- """
- docs_dir_location = os.path.join(PROJECT_DIRECTORY, '.ebextensions')
- if os.path.exists(docs_dir_location):
- shutil.rmtree(docs_dir_location)
-
- filenames = ["ebsetenv.py", ]
- if '{{ cookiecutter.use_heroku }}'.lower() != 'y':
- filenames.append("requirements.txt")
- for filename in filenames:
- os.remove(os.path.join(
- PROJECT_DIRECTORY, filename
- ))
-
-def remove_open_source_files():
- """
- Removes files conventional to opensource projects only.
- """
- for filename in ["CONTRIBUTORS.txt"]:
- os.remove(os.path.join(
- PROJECT_DIRECTORY, filename
- ))
-
# IN PROGRESS
# def copy_doc_files(project_directory):
@@ -221,26 +194,26 @@ def remove_open_source_files():
# dst = os.path.join(target_dir, name)
# shutil.copyfile(src, dst)
-# Generates and saves random secret key
+# 1. Generates and saves random secret key
make_secret_key(PROJECT_DIRECTORY)
-# Removes the taskapp if celery isn't going to be used
+# 2. Removes the taskapp if celery isn't going to be used
if '{{ cookiecutter.use_celery }}'.lower() == 'n':
remove_task_app(PROJECT_DIRECTORY)
-# Removes the .idea directory if PyCharm isn't going to be used
+# 3. Removes the .idea directory if PyCharm isn't going to be used
if '{{ cookiecutter.use_pycharm }}'.lower() != 'y':
remove_pycharm_dir(PROJECT_DIRECTORY)
-# Removes all heroku files if it isn't going to be used
+# 4. Removes all heroku files if it isn't going to be used
if '{{ cookiecutter.use_heroku }}'.lower() != 'y':
remove_heroku_files()
-# Removes all docker files if it isn't going to be used
+# 5. Removes all docker files if it isn't going to be used
if '{{ cookiecutter.use_docker }}'.lower() != 'y':
remove_docker_files()
-# Removes all JS task manager files if it isn't going to be used
+# 6. Removes all JS task manager files if it isn't going to be used
if '{{ cookiecutter.js_task_runner}}'.lower() == 'gulp':
remove_grunt_files()
elif '{{ cookiecutter.js_task_runner}}'.lower() == 'grunt':
@@ -250,7 +223,8 @@ else:
remove_grunt_files()
remove_packageJSON_file()
-# Display a warning if use_docker and use_grunt are selected. Grunt isn't
+
+# 9. Display a warning if use_docker and use_grunt are selected. Grunt isn't
# supported by our docker config atm.
if '{{ cookiecutter.js_task_runner }}'.lower() in ['grunt', 'gulp'] and '{{ cookiecutter.use_docker }}'.lower() == 'y':
print(
@@ -259,15 +233,6 @@ if '{{ cookiecutter.js_task_runner }}'.lower() in ['grunt', 'gulp'] and '{{ cook
"js task runner service to your docker configuration manually."
)
-
-# Removes files needed for the GPLv3 licence if it isn't going to be used.
+# 10. Removes files needed for the GPLv3 licence if it isn't going to be used.
if '{{ cookiecutter.open_source_license}}' != 'GPLv3':
remove_copying_files()
-
-# Remove Elastic Beanstalk files
-if '{{ cookiecutter.use_elasticbeanstalk_experimental }}'.lower() != 'y':
- remove_elasticbeanstalk()
-
-# Remove files conventional to opensource projects only.
-if '{{ cookiecutter.open_source_license }}' == 'Not open source':
- remove_open_source_files()
diff --git a/hooks/pre_gen_project.py b/hooks/pre_gen_project.py
index c7a68450..5f2c9d5d 100644
--- a/hooks/pre_gen_project.py
+++ b/hooks/pre_gen_project.py
@@ -3,13 +3,9 @@ project_slug = '{{ cookiecutter.project_slug }}'
if hasattr(project_slug, 'isidentifier'):
assert project_slug.isidentifier(), 'Project slug should be valid Python identifier!'
-elasticbeanstalk = '{{ cookiecutter.use_elasticbeanstalk_experimental }}'.lower()
heroku = '{{ cookiecutter.use_heroku }}'.lower()
docker = '{{ cookiecutter.use_docker }}'.lower()
-if elasticbeanstalk == 'y' and (heroku == 'y' or docker == 'y'):
- raise Exception("Cookiecutter Django's EXPERIMENTAL Elastic Beanstalk support is incompatible with Heroku and Docker setups.")
-
if docker == 'n':
import sys
@@ -26,6 +22,6 @@ if docker == 'n':
elif choice in yes_options:
pass
else:
- sys.stdout.write("Please respond with %s or %s"
+ sys.stdout.write("Please respond with %s or %s"
% (', '.join([o for o in yes_options if not o == ''])
, ', '.join([o for o in no_options if not o == ''])))
diff --git a/requirements.txt b/requirements.txt
index addeef31..1790a021 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -4,7 +4,7 @@ sh==1.12.14
binaryornot==0.4.4
# Testing
-pytest==3.3.1
+pytest==3.3.2
pycodestyle==2.3.1
pyflakes==1.6.0
tox==2.9.1
diff --git a/setup.py b/setup.py
index a300dc7f..eb5856e6 100644
--- a/setup.py
+++ b/setup.py
@@ -10,7 +10,7 @@ except ImportError:
# Our version ALWAYS matches the version of Django we support
# If Django has a new release, we branch, tag, then update this setting after the tag.
-version = '1.11.8'
+version = '1.11.9'
if sys.argv[-1] == 'tag':
os.system('git tag -a %s -m "version %s"' % (version, version))
diff --git a/{{cookiecutter.project_slug}}/.ebextensions/10_packages.config b/{{cookiecutter.project_slug}}/.ebextensions/10_packages.config
deleted file mode 100644
index 136be533..00000000
--- a/{{cookiecutter.project_slug}}/.ebextensions/10_packages.config
+++ /dev/null
@@ -1,7 +0,0 @@
-packages:
- yum:
- git: []
- postgresql94-devel: []
- libjpeg-turbo-devel: []
- libffi: []
- libffi-devel: []
diff --git a/{{cookiecutter.project_slug}}/.ebextensions/20_elasticcache.config b/{{cookiecutter.project_slug}}/.ebextensions/20_elasticcache.config
deleted file mode 100644
index 26c059e3..00000000
--- a/{{cookiecutter.project_slug}}/.ebextensions/20_elasticcache.config
+++ /dev/null
@@ -1,46 +0,0 @@
-#This sample requires you to create a separate configuration file that defines the custom
-# option settings for CacheCluster properties.
-
-Resources:
- MyCacheSecurityGroup:
- Type: "AWS::EC2::SecurityGroup"
- Properties:
- GroupDescription: "Lock cache down to webserver access only"
- SecurityGroupIngress :
- - IpProtocol : "tcp"
- FromPort :
- Fn::GetOptionSetting:
- OptionName : "CachePort"
- DefaultValue: "6379"
- ToPort :
- Fn::GetOptionSetting:
- OptionName : "CachePort"
- DefaultValue: "6379"
- SourceSecurityGroupName:
- Ref: "AWSEBSecurityGroup"
- MyElastiCache:
- Type: "AWS::ElastiCache::CacheCluster"
- Properties:
- CacheNodeType:
- Fn::GetOptionSetting:
- OptionName : "CacheNodeType"
- DefaultValue : "cache.t2.micro"
- NumCacheNodes:
- Fn::GetOptionSetting:
- OptionName : "NumCacheNodes"
- DefaultValue : "1"
- Engine:
- Fn::GetOptionSetting:
- OptionName : "Engine"
- DefaultValue : "redis"
- VpcSecurityGroupIds:
- -
- Fn::GetAtt:
- - MyCacheSecurityGroup
- - GroupId
-
-Outputs:
- ElastiCache:
- Description : "ID of ElastiCache Cache Cluster with Redis Engine"
- Value :
- Ref : "MyElastiCache"
diff --git a/{{cookiecutter.project_slug}}/.ebextensions/30_options.config b/{{cookiecutter.project_slug}}/.ebextensions/30_options.config
deleted file mode 100644
index fefec489..00000000
--- a/{{cookiecutter.project_slug}}/.ebextensions/30_options.config
+++ /dev/null
@@ -1,6 +0,0 @@
-option_settings:
- "aws:elasticbeanstalk:customoption":
- CacheNodeType : cache.t2.micro
- NumCacheNodes : 1
- Engine : redis
- CachePort : 6379
diff --git a/{{cookiecutter.project_slug}}/.ebextensions/40_python.config b/{{cookiecutter.project_slug}}/.ebextensions/40_python.config
deleted file mode 100644
index 03b91eb4..00000000
--- a/{{cookiecutter.project_slug}}/.ebextensions/40_python.config
+++ /dev/null
@@ -1,17 +0,0 @@
-container_commands:
- 01_migrate:
- command: "source /opt/python/run/venv/bin/activate && python manage.py migrate --noinput"
- leader_only: True
- 02_collectstatic:
- command: "source /opt/python/run/venv/bin/activate && python manage.py collectstatic --noinput"
-option_settings:
- "aws:elasticbeanstalk:application:environment":
- DJANGO_SETTINGS_MODULE: "config.settings.production"
- REDIS_ENDPOINT_ADDRESS: '`{ "Fn::GetAtt" : [ "MyElastiCache", "RedisEndpoint.Address"]}`'
- REDIS_PORT: '`{ "Fn::GetAtt" : [ "MyElastiCache", "RedisEndpoint.Port"]}`'
- "aws:elasticbeanstalk:container:python":
- WSGIPath: config/wsgi.py
- NumProcesses: 3
- NumThreads: 20
- "aws:elasticbeanstalk:container:python:staticfiles":
- "/static/": "www/static/"
diff --git a/{{cookiecutter.project_slug}}/.ebextensions/50_apache.config b/{{cookiecutter.project_slug}}/.ebextensions/50_apache.config
deleted file mode 100644
index 672cb625..00000000
--- a/{{cookiecutter.project_slug}}/.ebextensions/50_apache.config
+++ /dev/null
@@ -1,3 +0,0 @@
-container_commands:
- 01_setup_apache:
- command: "cp .ebextensions/enable_mod_deflate.conf /etc/httpd/conf.d/enable_mod_deflate.conf"
diff --git a/{{cookiecutter.project_slug}}/.ebextensions/enable_mod_deflate.conf b/{{cookiecutter.project_slug}}/.ebextensions/enable_mod_deflate.conf
deleted file mode 100644
index 7a77cc23..00000000
--- a/{{cookiecutter.project_slug}}/.ebextensions/enable_mod_deflate.conf
+++ /dev/null
@@ -1,25 +0,0 @@
-# mod_deflate configuration
-
- # Restrict compression to these MIME types
- AddOutputFilterByType DEFLATE text/plain
- AddOutputFilterByType DEFLATE text/html
- AddOutputFilterByType DEFLATE application/xhtml+xml
- AddOutputFilterByType DEFLATE text/xml
- AddOutputFilterByType DEFLATE application/xml
- AddOutputFilterByType DEFLATE application/xml+rss
- AddOutputFilterByType DEFLATE application/x-javascript
- AddOutputFilterByType DEFLATE text/javascript
- AddOutputFilterByType DEFLATE text/css
- # Level of compression (Highest 9 - Lowest 1)
- DeflateCompressionLevel 9
- # Netscape 4.x has some problems.
- BrowserMatch ^Mozilla/4 gzip-only-text/html
- # Netscape 4.06-4.08 have some more problems
- BrowserMatch ^Mozilla/4\.0[678] no-gzip
- # MSIE masquerades as Netscape, but it is fine
- BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html
-
- # Make sure proxies don't deliver the wrong content
- Header append Vary User-Agent env=!dont-vary
-
-
diff --git a/{{cookiecutter.project_slug}}/Gruntfile.js b/{{cookiecutter.project_slug}}/Gruntfile.js
index 6900c4e0..15384c67 100644
--- a/{{cookiecutter.project_slug}}/Gruntfile.js
+++ b/{{cookiecutter.project_slug}}/Gruntfile.js
@@ -61,7 +61,7 @@ module.exports = function (grunt) {
options: {
outputStyle: 'nested',
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
- includePaths: ['bower_components/bootstrap-sass/assets/stylesheets/bootstrap/'],
+ includePaths: ['node_modules/bootstrap/scss'],
{% endif %}
sourceMap: false,
precision: 10
@@ -74,7 +74,7 @@ module.exports = function (grunt) {
options: {
outputStyle: 'compressed',
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
- includePaths: ['bower_components/bootstrap-sass/assets/stylesheets/bootstrap/'],
+ includePaths: ['node_modules/bootstrap/scss'],
{% endif %}
sourceMap: false,
precision: 10
diff --git a/{{cookiecutter.project_slug}}/README.rst b/{{cookiecutter.project_slug}}/README.rst
index 924e238d..dc3495d5 100644
--- a/{{cookiecutter.project_slug}}/README.rst
+++ b/{{cookiecutter.project_slug}}/README.rst
@@ -79,8 +79,6 @@ Email Server
{% if cookiecutter.use_docker == 'y' %}
In development, it is often nice to be able to see emails that are being sent from your application. For that reason local SMTP server `MailHog`_ with a web interface is available as docker container.
-.. _mailhog: https://github.com/mailhog/MailHog
-
Container mailhog will start automatically when you will run all docker containers.
Please check `cookiecutter-django Docker documentation`_ for more details how to start all containers.
@@ -88,8 +86,6 @@ With MailHog running, to view messages that are sent by your application, open y
{% else %}
In development, it is often nice to be able to see emails that are being sent from your application. If you choose to use `MailHog`_ when generating the project a local SMTP server with a web interface will be available.
-.. _mailhog: https://github.com/mailhog/MailHog
-
To start the service, make sure you have nodejs installed, and then type the following::
$ npm install
@@ -101,6 +97,7 @@ To view messages that are sent by your application, open your browser and go to
The email server will exit when you exit the Grunt task on the CLI with Ctrl+C.
{% endif %}
+.. _mailhog: https://github.com/mailhog/MailHog
{% endif %}
{% if cookiecutter.use_sentry_for_error_reporting == "y" %}
@@ -135,22 +132,21 @@ See detailed `cookiecutter-django Docker documentation`_.
.. _`cookiecutter-django Docker documentation`: http://cookiecutter-django.readthedocs.io/en/latest/deployment-with-docker.html
{% endif %}
-{% if cookiecutter.use_elasticbeanstalk_experimental.lower() == 'y' %}
-Elastic Beanstalk
-~~~~~~~~~~~~~~~~~~
-
-See detailed `cookiecutter-django Elastic Beanstalk documentation`_.
-
-.. _`cookiecutter-django Docker documentation`: http://cookiecutter-django.readthedocs.io/en/latest/deployment-with-elastic-beanstalk.html
-
-{% endif %}
{% if cookiecutter.custom_bootstrap_compilation == "y" %}
Custom Bootstrap Compilation
^^^^^^
-To get automatic Bootstrap recompilation with variables of your choice, install bootstrap sass (`bower install bootstrap-sass`) and tweak your variables in `static/sass/custom_bootstrap_vars`.
+The generated CSS is set up with automatic Bootstrap recompilation with variables of your choice.
+Bootstrap v4 is installed using npm and customised by tweaking your variables in ``static/sass/custom_bootstrap_vars``.
-(You can find a list of available variables [in the bootstrap-sass source](https://github.com/twbs/bootstrap-sass/blob/master/assets/stylesheets/bootstrap/_variables.scss), or get explanations on them in the [Bootstrap docs](https://getbootstrap.com/customize/).)
+You can find a list of available variables `in the bootstrap source`_, or get explanations on them in the `Bootstrap docs`_.
+
+{% if cookiecutter.js_task_runner == 'Gulp' %}
+Bootstrap's javascript as well as its dependencies is concatenated into a single file: ``static/js/vendors.js``.
+{% endif %}
+
+.. _in the bootstrap source: https://github.com/twbs/bootstrap/blob/v4-dev/scss/_variables.scss
+.. _Bootstrap docs: https://getbootstrap.com/docs/4.0/getting-started/theming/
{% endif %}
diff --git a/{{cookiecutter.project_slug}}/config/settings/production.py b/{{cookiecutter.project_slug}}/config/settings/production.py
index db581306..33542fbf 100644
--- a/{{cookiecutter.project_slug}}/config/settings/production.py
+++ b/{{cookiecutter.project_slug}}/config/settings/production.py
@@ -172,36 +172,17 @@ TEMPLATES[0]['OPTIONS']['loaders'] = [
{% set _DEFAULT_CONN_MAX_AGE=60 %}
# DATABASE CONFIGURATION
# ------------------------------------------------------------------------------
-{% if cookiecutter.use_elasticbeanstalk_experimental.lower() == 'y' -%}
-# Uses Amazon RDS for database hosting, which doesn't follow the Heroku-style spec
-DATABASES = {
- 'default': {
- 'ENGINE': 'django.db.backends.postgresql_psycopg2',
- 'NAME': env('RDS_DB_NAME'),
- 'USER': env('RDS_USERNAME'),
- 'PASSWORD': env('RDS_PASSWORD'),
- 'HOST': env('RDS_HOSTNAME'),
- 'PORT': env('RDS_PORT'),
- 'CONN_MAX_AGE': env.int('CONN_MAX_AGE', default={{ _DEFAULT_CONN_MAX_AGE }}),
- }
-}
-{% else %}
+
# Use the Heroku-style specification
# Raises ImproperlyConfigured exception if DATABASE_URL not in os.environ
DATABASES['default'] = env.db('DATABASE_URL')
DATABASES['default']['CONN_MAX_AGE'] = env.int('CONN_MAX_AGE', default={{ _DEFAULT_CONN_MAX_AGE }})
-{%- endif %}
+
# CACHING
# ------------------------------------------------------------------------------
-{% if cookiecutter.use_elasticbeanstalk_experimental.lower() == 'y' -%}
-REDIS_LOCATION = 'redis://{}:{}/0'.format(
- env('REDIS_ENDPOINT_ADDRESS'),
- env('REDIS_PORT')
-)
-{% else %}
REDIS_LOCATION = '{0}/{1}'.format(env('REDIS_URL', default='redis://127.0.0.1:6379'), 0)
-{%- endif %}
+
# Heroku URL does not pass the DB number, so we parse it in
CACHES = {
'default': {
diff --git a/{{cookiecutter.project_slug}}/config/wsgi.py b/{{cookiecutter.project_slug}}/config/wsgi.py
index 601d27c6..5f49644c 100644
--- a/{{cookiecutter.project_slug}}/config/wsgi.py
+++ b/{{cookiecutter.project_slug}}/config/wsgi.py
@@ -20,7 +20,8 @@ from django.core.wsgi import get_wsgi_application
# This allows easy placement of apps within the interior
# {{ cookiecutter.project_slug }} directory.
-app_path = os.path.dirname(os.path.abspath(__file__)).replace('/config', '')
+app_path = os.path.abspath(os.path.join(
+ os.path.dirname(os.path.abspath(__file__)), os.pardir))
sys.path.append(os.path.join(app_path, '{{ cookiecutter.project_slug }}'))
{% if cookiecutter.use_sentry_for_error_reporting == 'y' -%}
diff --git a/{{cookiecutter.project_slug}}/ebsetenv.py b/{{cookiecutter.project_slug}}/ebsetenv.py
deleted file mode 100644
index ba9652db..00000000
--- a/{{cookiecutter.project_slug}}/ebsetenv.py
+++ /dev/null
@@ -1,37 +0,0 @@
-"""Converts a .env file to Elastic Beanstalk environment variables"""
-
-import os
-from sys import exit
-from subprocess import check_call
-
-try:
- import dotenv
-except ImportError:
- print("Please install the 'dotenv' library: 'pip install dotenv'")
- exit()
-
-def main():
- if not os.path.exists('.env'):
- print('ERROR!! .env file is missing!')
- print("Please copy 'env.example' to '.env' and add appropriate values")
- exit()
- command = ['eb', 'setenv']
- failures = []
- for key, value in dotenv.Dotenv('.env').items():
- if key.startswith('POSTGRES'):
- print('Skipping POSTGRES values - Amazon RDS provides these')
- continue
- if value:
- command.append("{}={}".format(key, value))
- else:
- failures.append(key)
- if failures:
- for failure in failures:
- print("{} requires a value".format(failure))
- else:
- print(' '.join(command))
- check_call(command)
-
-
-if __name__ == '__main__':
- main()
diff --git a/{{cookiecutter.project_slug}}/gulpfile.js b/{{cookiecutter.project_slug}}/gulpfile.js
index 594fa090..bb18a535 100644
--- a/{{cookiecutter.project_slug}}/gulpfile.js
+++ b/{{cookiecutter.project_slug}}/gulpfile.js
@@ -10,6 +10,9 @@ var gulp = require('gulp'),
sass = require('gulp-sass'),
autoprefixer = require('gulp-autoprefixer'),
cssnano = require('gulp-cssnano'),
+ {% if cookiecutter.custom_bootstrap_compilation == 'y' %}
+ concat = require('gulp-concat'),
+ {% endif %}
rename = require('gulp-rename'),
del = require('del'),
plumber = require('gulp-plumber'),
@@ -25,15 +28,24 @@ var gulp = require('gulp'),
// Relative paths function
var pathsConfig = function (appName) {
this.app = "./" + (appName || pjson.name);
+ var vendorsRoot = 'node_modules/';
return {
+ {% if cookiecutter.custom_bootstrap_compilation == 'y' %}
+ bootstrapSass: vendorsRoot + '/bootstrap/scss',
+ vendorsJs: [
+ vendorsRoot + 'jquery/dist/jquery.slim.js',
+ vendorsRoot + 'popper.js/dist/umd/popper.js',
+ vendorsRoot + 'bootstrap/dist/js/bootstrap.js'
+ ],
+ {% endif %}
app: this.app,
templates: this.app + '/templates',
css: this.app + '/static/css',
sass: this.app + '/static/sass',
fonts: this.app + '/static/fonts',
images: this.app + '/static/images',
- js: this.app + '/static/js',
+ js: this.app + '/static/js'
}
};
@@ -45,8 +57,15 @@ var paths = pathsConfig();
// Styles autoprefixing and minification
gulp.task('styles', function() {
- return gulp.src(paths.sass + '/*.scss')
- .pipe(sass().on('error', sass.logError))
+ return gulp.src(paths.sass + '/project.scss')
+ .pipe(sass({
+ includePaths: [
+ {% if cookiecutter.custom_bootstrap_compilation == 'y' %}
+ paths.bootstrapSass,
+ {% endif %}
+ paths.sass
+ ]
+ }).on('error', sass.logError))
.pipe(plumber()) // Checks for errors
.pipe(autoprefixer({browsers: ['last 2 versions']})) // Adds vendor prefixes
.pipe(pixrem()) // add fallbacks for rem units
@@ -65,6 +84,20 @@ gulp.task('scripts', function() {
.pipe(gulp.dest(paths.js));
});
+
+{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
+// Vendor Javascript minification
+gulp.task('vendor-scripts', function() {
+ return gulp.src(paths.vendorsJs)
+ .pipe(concat('vendors.js'))
+ .pipe(gulp.dest(paths.js))
+ .pipe(plumber()) // Checks for errors
+ .pipe(uglify()) // Minifies the js
+ .pipe(rename({ suffix: '.min' }))
+ .pipe(gulp.dest(paths.js));
+});
+{% endif %}
+
// Image compression
gulp.task('imgCompression', function(){
return gulp.src(paths.images + '/*')
@@ -101,5 +134,5 @@ gulp.task('watch', function() {
// Default task
gulp.task('default', function() {
- runSequence(['styles', 'scripts', 'imgCompression'], ['runServer', 'browserSync', 'watch']);
+ runSequence(['styles', 'scripts', {% if cookiecutter.custom_bootstrap_compilation == 'y' %}'vendor-scripts', {% endif %}'imgCompression'], ['runServer', 'browserSync', 'watch']);
});
diff --git a/{{cookiecutter.project_slug}}/package.json b/{{cookiecutter.project_slug}}/package.json
index 0c8af427..a37d73bf 100644
--- a/{{cookiecutter.project_slug}}/package.json
+++ b/{{cookiecutter.project_slug}}/package.json
@@ -5,6 +5,9 @@
"devDependencies": {
{% if cookiecutter.js_task_runner == 'Grunt' %}
"autoprefixer-core": "~5.2.1",
+ {% if cookiecutter.custom_bootstrap_compilation == 'y' %}
+ "bootstrap": "^4.0.0",
+ {% endif %}
"connect-livereload": "~0.3.2",
"cssnano": "~2.1.0",
"grunt": "~0.4.5",
@@ -12,14 +15,26 @@
"grunt-contrib-watch": "~0.6.1",
"grunt-postcss": "~0.5.5",
"grunt-sass": "~1.0.0",
+ {% if cookiecutter.custom_bootstrap_compilation == 'y' %}
+ "jquery": "^3.2.1-slim",
+ {% endif %}
"load-grunt-tasks": "~3.2.0",
"pixrem": "~1.3.1",
+ {% if cookiecutter.custom_bootstrap_compilation == 'y' %}
+ "popper.js": "^1.12.3",
+ {% endif %}
"time-grunt": "~1.2.1"
{% elif cookiecutter.js_task_runner == 'Gulp' %}
+ {% if cookiecutter.custom_bootstrap_compilation == 'y' %}
+ "bootstrap": "^4.0.0",
+ {% endif %}
"browser-sync": "^2.14.0",
"del": "^2.2.2",
"gulp": "^3.9.1",
"gulp-autoprefixer": "^3.1.1",
+ {% if cookiecutter.custom_bootstrap_compilation == 'y' %}
+ "gulp-concat": "^2.6.1",
+ {% endif %}
"gulp-cssnano": "^2.1.2",
"gulp-imagemin": "^3.0.3",
"gulp-pixrem": "^1.0.0",
@@ -28,6 +43,10 @@
"gulp-sass": "^2.3.2",
"gulp-uglify": "^2.0.0",
"gulp-util": "^3.0.7",
+ {% if cookiecutter.custom_bootstrap_compilation == 'y' %}
+ "jquery": "^3.2.1-slim",
+ "popper.js": "^1.12.3",
+ {% endif %}
"run-sequence": "^1.2.2"
{% endif %}
},
diff --git a/{{cookiecutter.project_slug}}/requirements/base.txt b/{{cookiecutter.project_slug}}/requirements/base.txt
index b7de5975..62fde368 100644
--- a/{{cookiecutter.project_slug}}/requirements/base.txt
+++ b/{{cookiecutter.project_slug}}/requirements/base.txt
@@ -19,17 +19,17 @@ whitenoise==3.3.1
django-crispy-forms==1.7.0
# Models
-django-model-utils==3.0.0
+django-model-utils==3.1.1
# Images
-Pillow==4.3.0
+Pillow==5.0.0
# Password storage
-argon2-cffi==16.3.0
+argon2-cffi==18.1.0
# For user registration, either via email or social
# Well-built with regular release cycles!
-django-allauth==0.34.0
+django-allauth==0.35.0
{% if cookiecutter.windows == 'y' -%}
# On Windows, you must download/install psycopg2 manually
diff --git a/{{cookiecutter.project_slug}}/requirements/local.txt b/{{cookiecutter.project_slug}}/requirements/local.txt
index f86cae8c..fad86434 100644
--- a/{{cookiecutter.project_slug}}/requirements/local.txt
+++ b/{{cookiecutter.project_slug}}/requirements/local.txt
@@ -1,14 +1,14 @@
# Local development dependencies go here
-r base.txt
-coverage==4.4.2
+coverage==4.5
django-coverage-plugin==1.5.0
-Sphinx==1.6.5
-django-extensions==1.9.8
-Werkzeug==0.13
-django-test-plus==1.0.21
-factory-boy==2.9.2
+Sphinx==1.6.6
+django-extensions==1.9.9
+Werkzeug==0.14.1
+django-test-plus==1.0.22
+factory-boy==2.10.0
django-debug-toolbar==1.9.1
diff --git a/{{cookiecutter.project_slug}}/requirements/production.txt b/{{cookiecutter.project_slug}}/requirements/production.txt
index 603fdb80..15740618 100644
--- a/{{cookiecutter.project_slug}}/requirements/production.txt
+++ b/{{cookiecutter.project_slug}}/requirements/production.txt
@@ -16,7 +16,7 @@ gunicorn==19.7.1
# Static and Media Storage
# ------------------------------------------------
-boto3==1.5.6
+boto3==1.5.22
django-storages==1.6.5
{% if cookiecutter.use_whitenoise != 'y' -%}
Collectfast==0.6.0
@@ -24,16 +24,16 @@ Collectfast==0.6.0
# Email backends for Mailgun, Postmark, SendGrid and more
# -------------------------------------------------------
-django-anymail==1.2
+django-anymail==1.3
{% if cookiecutter.use_sentry_for_error_reporting == "y" -%}
# Raven is the Sentry client
# --------------------------
-raven==6.4.0
+raven==6.5.0
{%- endif %}
{% if cookiecutter.use_opbeat == "y" -%}
# Opbeat agent for performance monitoring
# -----------------------------------------
-opbeat==3.6.0
+opbeat==3.6.1
{%- endif %}
diff --git a/{{cookiecutter.project_slug}}/requirements/test.txt b/{{cookiecutter.project_slug}}/requirements/test.txt
index 31ab8ff1..b5a8ec98 100644
--- a/{{cookiecutter.project_slug}}/requirements/test.txt
+++ b/{{cookiecutter.project_slug}}/requirements/test.txt
@@ -7,10 +7,10 @@
psycopg2==2.7.3.2
{%- endif %}
-coverage==4.4.2
+coverage==4.5
flake8==3.5.0 # pyup: != 2.6.0
-django-test-plus==1.0.21
-factory-boy==2.9.2
+django-test-plus==1.0.22
+factory-boy==2.10.0
django-coverage-plugin==1.5.0
# pytest
diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/sass/project.scss b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/sass/project.scss
index 6e701f29..3ba2e55a 100644
--- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/sass/project.scss
+++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/static/sass/project.scss
@@ -1,54 +1,6 @@
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
-@import "variables";
@import "custom_bootstrap_vars";
-@import "mixins";
-
-// Reset and dependencies
-@import "normalize";
-@import "print";
-@import "glyphicons";
-
-// Core CSS
-@import "scaffolding";
-@import "type";
-@import "code";
-@import "grid";
-@import "tables";
-@import "forms";
-@import "buttons";
-
-// Components
-@import "component-animations";
-@import "dropdowns";
-@import "button-groups";
-@import "input-groups";
-@import "navs";
-@import "navbar";
-@import "breadcrumbs";
-@import "pagination";
-@import "pager";
-@import "labels";
-@import "badges";
-@import "jumbotron";
-@import "thumbnails";
-@import "alerts";
-@import "progress-bars";
-@import "media";
-@import "list-group";
-@import "panels";
-@import "responsive-embed";
-@import "wells";
-@import "close";
-
-// Components w/ JavaScript
-@import "modals";
-@import "tooltip";
-@import "popovers";
-@import "carousel";
-
-// Utility classes
-@import "utilities";
-@import "responsive-utilities";
+@import "bootstrap";
{% endif %}
diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/base.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/base.html
index 6fdc1798..a45de763 100644
--- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/base.html
+++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/base.html
@@ -14,13 +14,19 @@
{% block css %}
+ {% endraw %}{% if cookiecutter.custom_bootstrap_compilation == "n" %}{% raw %}
+ {% endraw %}{% endif %}{% raw %}
{% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% compress css %}{% endraw %}{% endif %}{% raw %}
+ {% endraw %}{% if cookiecutter.js_task_runner == "Gulp" %}{% raw %}
+
+ {% endraw %}{% else %}{% raw %}
+ {% endraw %}{% endif %}{% raw %}
{% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% endcompress %}{% endraw %}{% endif %}{% raw %}
{% endblock %}
@@ -88,12 +94,19 @@
================================================== -->
{% block javascript %}
+ {% endraw %}{% if cookiecutter.custom_bootstrap_compilation == "y" and cookiecutter.js_task_runner == "Gulp" %}{% raw %}
+
+ {% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% compress js %}{% endraw %}{% endif %}{% raw %}
+
+ {% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% endcompress %}{% endraw %}{% endif %}{% raw %}
+ {% endraw %}{% else %}{% raw %}
+ {% endraw %}{% endif %}{% raw %}
{% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% compress js %}{% endraw %}{% endif %}{% raw %}