├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── MANIFEST.in ├── README.md ├── requirements.txt ├── setup.py ├── test_requirements.txt └── zappa_django_utils ├── __init__.py ├── admin.py ├── db ├── __init__.py └── backends │ ├── __init__.py │ └── s3sqlite │ ├── __init__.py │ ├── base.py │ ├── client.py │ └── features.py ├── management ├── __init__.py └── commands │ ├── __init__.py │ ├── create_admin_user.py │ ├── create_mysql_db.py │ ├── create_pg_db.py │ ├── create_pg_schema.py │ ├── drop_pg_db.py │ ├── drop_pg_schema.py │ └── s3sqlite_vacuum.py ├── migrations └── __init__.py ├── models.py ├── urls.py └── views.py /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.zip 3 | 4 | # Byte-compiled / optimized / DLL files 5 | __pycache__/ 6 | *.py[cod] 7 | *$py.class 8 | 9 | # C extensions 10 | *.so 11 | 12 | # Distribution / packaging 13 | .Python 14 | env/ 15 | build/ 16 | develop-eggs/ 17 | dist/ 18 | downloads/ 19 | eggs/ 20 | .eggs/ 21 | lib/ 22 | lib64/ 23 | parts/ 24 | sdist/ 25 | var/ 26 | *.egg-info/ 27 | .installed.cfg 28 | *.egg 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .coverage 44 | .coveragerc 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *,cover 50 | .hypothesis/ 51 | 52 | # Translations 53 | *.mo 54 | *.pot 55 | 56 | # Django stuff: 57 | *.log 58 | 59 | # Sphinx documentation 60 | docs/_build/ 61 | 62 | # PyBuilder 63 | target/ 64 | 65 | # pyenv 66 | .python-version 67 | 68 | # PyCharm 69 | # Project settings from the PyCharm IDE are stored in the .idea folder 70 | .idea/ 71 | 72 | # Apple OS X specific files are put into the .DS_Store file 73 | .DS_Store 74 | 75 | # Vim stuff: 76 | *.swp 77 | *.swo 78 | *~ 79 | tests/zappa_settings.json 80 | tests/example_template_outputs 81 | 82 | # Locally generated settings file 83 | zappa_settings.json 84 | 85 | # Sublime Text stuff 86 | *.sublime-project 87 | *.sublime-workspace 88 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "2.7" 4 | - "3.6" 5 | # command to install dependencies 6 | cache: 7 | - pip 8 | install: 9 | - "pip install setuptools --upgrade; pip install -r test_requirements.txt; pip install -e git+https://github.com/django/django-contrib-comments.git#egg=django-contrib-comments; python setup.py install" 10 | # command to run tests 11 | env: 12 | - TESTCASE=tests/test_handler.py 13 | - TESTCASE=tests/tests_middleware.py 14 | - TESTCASE=tests/tests_placebo.py 15 | - TESTCASE=tests/tests_async.py 16 | - TESTCASE=tests/tests.py 17 | script: 18 | - nosetests $TESTCASE --with-coverage --cover-package=zappa --with-timer 19 | # - coverage combine --append 20 | after_success: 21 | coveralls 22 | notifications: 23 | slack: zappateam:TTJ0mfHunDK0IBweKkEXjGpR 24 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG 2 | 3 | ## 0.3.1 4 | * Fix create PG DB 5 | 6 | ## 0.3.0 7 | * Add S3SQlite 8 | 9 | ## 0.2.0 10 | * Add/Drop schema 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Rich Jones 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.md LICENSE requirements.txt test_requirements.txt 2 | recursive-include zappa_django_utils *.py 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # zappa-django-utils 0.4.1: final release! 2 | 3 | [![PyPI](https://img.shields.io/pypi/v/zappa-django-utils.svg)](https://pypi.python.org/pypi/zappa-django-utils) 4 | [![Slack](https://img.shields.io/badge/chat-slack-ff69b4.svg)](https://slack.zappa.io/) 5 | [![Gun.io](https://img.shields.io/badge/made%20by-gun.io-blue.svg)](https://gun.io/) 6 | [![Patreon](https://img.shields.io/badge/support-patreon-brightgreen.svg)](https://patreon.com/zappa) 7 | 8 | # Final Release 9 | 10 | Thanks to everyone who has supported this package of Zappa utilities for Django! Many of these utilities have become deprecated as new features have been added to AWS, or split into their own projects such a `django-s3-sqlite`: https://github.com/flipperpa/django-s3-sqlite 11 | 12 | We're making one final release and will not be accepting further issues or pull requests. 13 | 14 | # Description 15 | 16 | Small utilities for making [Zappa](https://github.com/Miserlou/Zappa) deployments slightly easier for Django applications. 17 | 18 | This project was inspired by Edgar Roman's [Zappa Django Guide](https://github.com/edgarroman/zappa-django-guide). 19 | 20 | ## Installation 21 | 22 | Install via `pip`: 23 | 24 | $ pip install zappa-django-utils 25 | 26 | Add to your installed apps: 27 | 28 | INSTALLED_APPS += ['zappa_django_utils'] 29 | 30 | ## Usage 31 | 32 | ### Using an S3-Backed Database Engine - DEPRECATED! 33 | 34 | Use `django-s3-sqlite` instead, as it has an updated SQLite driver compatible with current versions of Django: 35 | 36 | https://github.com/flipperpa/django-s3-sqlite 37 | 38 | ### Creating a Postgres Database 39 | 40 | Once you have your RDS set up, your VPC/Subnet/Security Groups set up, and your `DATABASES` setting set up, you can create the database with: 41 | 42 | $ zappa manage create_pg_db 43 | 44 | Then you're ready to `python manage.py makemigrations` and `zappa update; zappa manage migrate`! 45 | 46 | ### Creating a Default Admin User 47 | 48 | You'll probably need a default user to manage your application with, so you can now: 49 | 50 | $ zappa manage create_admin_user 51 | 52 | Or you can pass some arguments: 53 | 54 | $ zappa manage create_admin_user one two three 55 | 56 | This will internally make this call: 57 | 58 | ```python 59 | User.objects.create_superuser('one', 'two', 'three') 60 | ``` 61 | 62 | Now log in and immediately change the admin user's email and password. 63 | 64 | ### Creating/Dropping a Postgres Schema 65 | 66 | You can create a [Postgres schema](https://www.postgresql.org/docs/current/static/ddl-schemas.html) with: 67 | 68 | $ zappa manage create_pg_schema 69 | 70 | and drop it with: 71 | 72 | $ zappa manage drop_pg_schema 73 | 74 | ## License 75 | 76 | (c) 2017, Rich Jones, MIT License 77 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Django>=1.9 2 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | from setuptools import setup 4 | from io import open 5 | 6 | # New PyPI handles markdown! Yay! 7 | with open('README.md') as f: 8 | README = f.read() 9 | 10 | # Set external files 11 | with open(os.path.join(os.path.dirname(__file__), 'requirements.txt')) as f: 12 | required = f.read().splitlines() 13 | 14 | with open(os.path.join(os.path.dirname(__file__), 'test_requirements.txt')) as f: 15 | test_required = f.read().splitlines() 16 | 17 | setup( 18 | name='zappa-django-utils', 19 | version='0.4.1', 20 | packages=['zappa_django_utils'], 21 | install_requires=required, 22 | tests_require=test_required, 23 | test_suite='nose.collector', 24 | include_package_data=True, 25 | license='MIT License', 26 | description='Helpers for Django Zappa deployments', 27 | long_description=README, 28 | long_description_content_type='text/markdown', 29 | url='https://github.com/Miserlou/zappa-django-utils', 30 | author='Rich Jones', 31 | author_email='rich@openwatch.net', 32 | classifiers=[ 33 | 'Environment :: Console', 34 | 'License :: OSI Approved :: Apache Software License', 35 | 'Operating System :: OS Independent', 36 | 'Programming Language :: Python', 37 | 'Programming Language :: Python :: 2', 38 | 'Programming Language :: Python :: 2.7', 39 | 'Programming Language :: Python :: 3', 40 | 'Programming Language :: Python :: 3.6', 41 | 'Framework :: Django', 42 | 'Framework :: Django :: 1.11', 43 | 'Framework :: Django :: 2.0', 44 | 'Topic :: Internet :: WWW/HTTP', 45 | 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', 46 | ], 47 | ) 48 | -------------------------------------------------------------------------------- /test_requirements.txt: -------------------------------------------------------------------------------- 1 | coveralls>=1.1 2 | coverage>=4.3.1 3 | Django>=1.10.5 4 | Flask>=0.12 5 | mock>=2.0.0 6 | nose>=1.3.7 7 | nose-timer>=0.6.0 8 | placebo>=0.8.1 9 | -------------------------------------------------------------------------------- /zappa_django_utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miserlou/zappa-django-utils/64e93f408375f181f54a00d81ec8667004142322/zappa_django_utils/__init__.py -------------------------------------------------------------------------------- /zappa_django_utils/admin.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miserlou/zappa-django-utils/64e93f408375f181f54a00d81ec8667004142322/zappa_django_utils/admin.py -------------------------------------------------------------------------------- /zappa_django_utils/db/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miserlou/zappa-django-utils/64e93f408375f181f54a00d81ec8667004142322/zappa_django_utils/db/__init__.py -------------------------------------------------------------------------------- /zappa_django_utils/db/backends/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miserlou/zappa-django-utils/64e93f408375f181f54a00d81ec8667004142322/zappa_django_utils/db/backends/__init__.py -------------------------------------------------------------------------------- /zappa_django_utils/db/backends/s3sqlite/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miserlou/zappa-django-utils/64e93f408375f181f54a00d81ec8667004142322/zappa_django_utils/db/backends/s3sqlite/__init__.py -------------------------------------------------------------------------------- /zappa_django_utils/db/backends/s3sqlite/base.py: -------------------------------------------------------------------------------- 1 | from django.db.backends.sqlite3.base import DatabaseWrapper 2 | 3 | from io import BytesIO 4 | 5 | import boto3 6 | import botocore 7 | import hashlib 8 | import logging 9 | import os 10 | 11 | 12 | class DatabaseWrapper(DatabaseWrapper): 13 | """ 14 | Wraps the normal Django SQLite DB engine in an S3 backer! 15 | 16 | """ 17 | 18 | def load_remote_db(self): 19 | """ 20 | Load remote S3 DB 21 | """ 22 | 23 | signature_version = self.settings_dict.get("SIGNATURE_VERSION", "s3v4") 24 | s3 = boto3.resource( 25 | 's3', 26 | config=botocore.client.Config(signature_version=signature_version), 27 | ) 28 | 29 | if '/tmp/' not in self.settings_dict['NAME']: 30 | try: 31 | etag = '' 32 | if os.path.isfile('/tmp/' + self.settings_dict['NAME']): 33 | m = hashlib.md5() 34 | with open('/tmp/' + self.settings_dict['NAME'], 'rb') as f: 35 | m.update(f.read()) 36 | 37 | # In general the ETag is the md5 of the file, in some cases it's not, 38 | # and in that case we will just need to reload the file, I don't see any other way 39 | etag = m.hexdigest() 40 | 41 | obj = s3.Object(self.settings_dict['BUCKET'], self.settings_dict['NAME']) 42 | obj_bytes = obj.get(IfNoneMatch=etag)["Body"] # Will throw E on 304 or 404 43 | 44 | with open('/tmp/' + self.settings_dict['NAME'], 'wb') as f: 45 | f.write(obj_bytes.read()) 46 | 47 | m = hashlib.md5() 48 | with open('/tmp/' + self.settings_dict['NAME'], 'rb') as f: 49 | m.update(f.read()) 50 | 51 | self.db_hash = m.hexdigest() 52 | 53 | except botocore.exceptions.ClientError as e: 54 | if e.response['Error']['Code'] == "304": 55 | logging.debug("ETag matches md5 of local copy, using local copy of DB!") 56 | self.db_hash = etag 57 | else: 58 | logging.debug("Couldn't load remote DB object.") 59 | except Exception as e: 60 | # Weird one 61 | logging.debug(e) 62 | 63 | # SQLite DatabaseWrapper will treat our tmp as normal now 64 | # Check because Django likes to call this function a lot more than it should 65 | if '/tmp/' not in self.settings_dict['NAME']: 66 | self.settings_dict['REMOTE_NAME'] = self.settings_dict['NAME'] 67 | self.settings_dict['NAME'] = '/tmp/' + self.settings_dict['NAME'] 68 | 69 | # Make sure it exists if it doesn't yet 70 | if not os.path.isfile(self.settings_dict['NAME']): 71 | open(self.settings_dict['NAME'], 'a').close() 72 | 73 | logging.debug("Loaded remote DB!") 74 | 75 | def __init__(self, *args, **kwargs): 76 | super(DatabaseWrapper, self).__init__(*args, **kwargs) 77 | self.db_hash = None 78 | self.load_remote_db() 79 | 80 | def close(self, *args, **kwargs): 81 | """ 82 | Engine closed, copy file to DB if it has changed 83 | """ 84 | super(DatabaseWrapper, self).close(*args, **kwargs) 85 | 86 | signature_version = self.settings_dict.get("SIGNATURE_VERSION", "s3v4") 87 | s3 = boto3.resource( 88 | 's3', 89 | config=botocore.client.Config(signature_version=signature_version), 90 | ) 91 | 92 | try: 93 | with open(self.settings_dict['NAME'], 'rb') as f: 94 | fb = f.read() 95 | 96 | m = hashlib.md5() 97 | m.update(fb) 98 | if self.db_hash == m.hexdigest(): 99 | logging.debug("Database unchanged, not saving to remote DB!") 100 | return 101 | 102 | bytesIO = BytesIO() 103 | bytesIO.write(fb) 104 | bytesIO.seek(0) 105 | 106 | s3_object = s3.Object(self.settings_dict['BUCKET'], self.settings_dict['REMOTE_NAME']) 107 | result = s3_object.put('rb', Body=bytesIO) 108 | except Exception as e: 109 | logging.debug(e) 110 | 111 | logging.debug("Saved to remote DB!") 112 | -------------------------------------------------------------------------------- /zappa_django_utils/db/backends/s3sqlite/client.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | 3 | from django.db.backends.base.client import BaseDatabaseClient 4 | 5 | 6 | class DatabaseClient(BaseDatabaseClient): 7 | executable_name = 'sqlite3' 8 | 9 | def runshell(self): 10 | args = [ 11 | self.executable_name, 12 | self.connection.settings_dict['NAME'], 13 | ] 14 | 15 | subprocess.check_call(args) 16 | -------------------------------------------------------------------------------- /zappa_django_utils/db/backends/s3sqlite/features.py: -------------------------------------------------------------------------------- 1 | from django.db.backends.base.features import BaseDatabaseFeatures 2 | -------------------------------------------------------------------------------- /zappa_django_utils/management/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miserlou/zappa-django-utils/64e93f408375f181f54a00d81ec8667004142322/zappa_django_utils/management/__init__.py -------------------------------------------------------------------------------- /zappa_django_utils/management/commands/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miserlou/zappa-django-utils/64e93f408375f181f54a00d81ec8667004142322/zappa_django_utils/management/commands/__init__.py -------------------------------------------------------------------------------- /zappa_django_utils/management/commands/create_admin_user.py: -------------------------------------------------------------------------------- 1 | from django.core.management.base import BaseCommand 2 | from django.contrib.auth import get_user_model 3 | 4 | import random 5 | import string 6 | 7 | 8 | class Command(BaseCommand): 9 | """ 10 | This command will create a default Django admin superuser. 11 | """ 12 | help = 'Creates a Django admin superuser.' 13 | 14 | def add_arguments(self, parser): 15 | parser.add_argument('arguments', nargs='*') 16 | 17 | def handle(self, *args, **options): 18 | # Gets the model for the current Django project's user. 19 | # This handles custom user models as well as Django's default. 20 | User = get_user_model() 21 | 22 | self.stdout.write(self.style.SUCCESS('Creating a new admin superuser...')) 23 | 24 | # If the command args are given -> try to create user with given args 25 | if options['arguments']: 26 | try: 27 | user = User.objects.create_superuser(*options['arguments']) 28 | self.stdout.write( 29 | self.style.SUCCESS( 30 | 'Created the admin superuser "{user}" with the given parameters.'.format( 31 | user=user, 32 | ) 33 | ) 34 | ) 35 | except Exception as e: 36 | self.stdout.write('ERROR: Django returned an error when creating the admin superuser:') 37 | self.stdout.write(str(e)) 38 | self.stdout.write('') 39 | self.stdout.write('The arguments expected by the command are in this order:') 40 | self.stdout.write(str(User.objects.create_superuser.__code__.co_varnames[1:-1])) 41 | 42 | # or create default admin user 43 | else: 44 | pw = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(10)) 45 | User.objects.create_superuser(username='admin', email='admin@admin.com', password=pw) 46 | self.stdout.write(self.style.SUCCESS('Created user "admin", email: "admin@admin.com", password: ' + pw)) 47 | self.stdout.write(self.style.SUCCESS('Log in and change this password immediately!')) 48 | -------------------------------------------------------------------------------- /zappa_django_utils/management/commands/create_mysql_db.py: -------------------------------------------------------------------------------- 1 | from django.core.management.base import BaseCommand 2 | from django.conf import settings 3 | 4 | import MySQLdb as db 5 | 6 | 7 | class Command(BaseCommand): 8 | help = "Create a database from settings file prior to migrations." 9 | 10 | def add_arguments(self, parser): 11 | parser.add_argument( 12 | '--user', 13 | dest='user', 14 | help='Username to be used to create database', 15 | ) 16 | parser.add_argument( 17 | '--password', 18 | dest='password', 19 | help='Password for the mysql user.', 20 | ) 21 | parser.add_argument( 22 | '--db-name', 23 | dest='db_name', 24 | help='Name of the database if it is different from the one defined in settings', 25 | ) 26 | 27 | def handle(self, *args, **options): 28 | self.stdout.write(self.style.SUCCESS('Starting db creation')) 29 | 30 | dbname = options.get('db_name') or settings.DATABASES['default']['NAME'] 31 | user = options.get('user') or settings.DATABASES['default']['USER'] 32 | password = options.get('password') or settings.DATABASES['default']['PASSWORD'] 33 | host = settings.DATABASES['default']['HOST'] 34 | 35 | con = db.connect(user=user, host=host, password=password) 36 | cur = con.cursor() 37 | cur.execute(f'CREATE DATABASE {dbname}') 38 | cur.execute(f'ALTER DATABASE `{dbname}` CHARACTER SET utf8') 39 | cur.close() 40 | con.close() 41 | 42 | self.stdout.write(self.style.SUCCESS('All Done')) 43 | -------------------------------------------------------------------------------- /zappa_django_utils/management/commands/create_pg_db.py: -------------------------------------------------------------------------------- 1 | from psycopg2 import connect 2 | from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT 3 | from django.core.management.base import BaseCommand 4 | from django.conf import settings 5 | 6 | 7 | class Command(BaseCommand): 8 | help = 'Creates the initial Postgres database' 9 | 10 | def handle(self, *args, **options): 11 | self.stdout.write(self.style.SUCCESS('Starting DB creation..')) 12 | 13 | dbname = settings.DATABASES['default']['NAME'] 14 | user = settings.DATABASES['default']['USER'] 15 | password = settings.DATABASES['default']['PASSWORD'] 16 | host = settings.DATABASES['default']['HOST'] 17 | 18 | self.stdout.write(self.style.SUCCESS('Connecting to host..')) 19 | con = connect(dbname='postgres', user=user, host=host, password=password) 20 | con.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) 21 | 22 | self.stdout.write(self.style.SUCCESS('Creating database')) 23 | cur = con.cursor() 24 | cur.execute('CREATE DATABASE ' + dbname) 25 | cur.close() 26 | 27 | con.close() 28 | 29 | self.stdout.write(self.style.SUCCESS('All done!')) 30 | -------------------------------------------------------------------------------- /zappa_django_utils/management/commands/create_pg_schema.py: -------------------------------------------------------------------------------- 1 | from psycopg2 import connect 2 | from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT 3 | from django.core.management.base import BaseCommand 4 | from django.conf import settings 5 | 6 | 7 | class Command(BaseCommand): 8 | help = 'Adds a schema to the database.' 9 | 10 | def handle(self, *args, **options): 11 | self.stdout.write(self.style.SUCCESS('Starting Schema creation..')) 12 | 13 | dbname = settings.DATABASES['default']['NAME'] 14 | user = settings.DATABASES['default']['USER'] 15 | password = settings.DATABASES['default']['PASSWORD'] 16 | host = settings.DATABASES['default']['HOST'] 17 | 18 | con = connect(dbname=dbname, user=user, host=host, password=password) 19 | 20 | self.stdout.write(self.style.SUCCESS('Adding schema {schema} to database {dbname}' 21 | .format(schema=settings.SCHEMA, dbname=dbname))) 22 | con.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) 23 | 24 | cur = con.cursor() 25 | cur.execute('CREATE SCHEMA {schema};'.format(schema=settings.SCHEMA)) 26 | cur.close() 27 | 28 | con.close() 29 | 30 | self.stdout.write(self.style.SUCCESS('All Done!')) 31 | -------------------------------------------------------------------------------- /zappa_django_utils/management/commands/drop_pg_db.py: -------------------------------------------------------------------------------- 1 | from psycopg2 import connect 2 | from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT 3 | from django.core.management.base import BaseCommand 4 | from django.conf import settings 5 | 6 | 7 | class Command(BaseCommand): 8 | help = 'Drop the Postgres database completely' 9 | 10 | def handle(self, *args, **options): 11 | self.stdout.write(self.style.SUCCESS('Starting to drop DB..')) 12 | 13 | dbname = settings.DATABASES['default']['NAME'] 14 | user = settings.DATABASES['default']['USER'] 15 | password = settings.DATABASES['default']['PASSWORD'] 16 | host = settings.DATABASES['default']['HOST'] 17 | 18 | self.stdout.write(self.style.SUCCESS('Connecting to host..')) 19 | con = connect(dbname='postgres', user=user, host=host, password=password) 20 | con.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) 21 | 22 | self.stdout.write(self.style.SUCCESS("Dropping database '{}'".format(dbname))) 23 | cur = con.cursor() 24 | cur.execute('DROP DATABASE ' + dbname) 25 | cur.close() 26 | 27 | con.close() 28 | 29 | self.stdout.write(self.style.SUCCESS('All done!')) 30 | -------------------------------------------------------------------------------- /zappa_django_utils/management/commands/drop_pg_schema.py: -------------------------------------------------------------------------------- 1 | from psycopg2 import connect 2 | from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT 3 | from django.core.management.base import BaseCommand 4 | from django.conf import settings 5 | 6 | 7 | class Command(BaseCommand): 8 | """ 9 | Command to drop a schema from a PostgreSQL database. 10 | """ 11 | help = 'Drops a schema from the PostgreSQL database.' 12 | 13 | def handle(self, *args, **options): 14 | self.stdout.write(self.style.SUCCESS('Starting schema deletion...')) 15 | 16 | dbname = settings.DATABASES['default']['NAME'] 17 | user = settings.DATABASES['default']['USER'] 18 | password = settings.DATABASES['default']['PASSWORD'] 19 | host = settings.DATABASES['default']['HOST'] 20 | 21 | con = connect(dbname=dbname, user=user, host=host, password=password) 22 | 23 | self.stdout.write(self.style.SUCCESS('Removing schema {schema} from database {dbname}' 24 | .format(schema=settings.SCHEMA, dbname=dbname))) 25 | con.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) 26 | 27 | cur = con.cursor() 28 | cur.execute('DROP SCHEMA {schema} CASCADE;'.format(schema=settings.SCHEMA)) 29 | cur.close() 30 | 31 | con.close() 32 | 33 | self.stdout.write(self.style.SUCCESS('All done.')) 34 | -------------------------------------------------------------------------------- /zappa_django_utils/management/commands/s3sqlite_vacuum.py: -------------------------------------------------------------------------------- 1 | from django.core.management.base import BaseCommand 2 | from django.db import connection, DatabaseError 3 | from django.conf import settings 4 | 5 | 6 | class Command(BaseCommand): 7 | """ 8 | This command performs a vacuum on the S3SQLite database. 9 | It is good to do this occasionally to keep the SQLite database stored 10 | on S3 as small and unfragmented as possible. It is recommended to be 11 | run after deleting data. 12 | """ 13 | help = 'Performs a vacuum command on a S3 stored SQLite database to minimize size and fragmentation.' 14 | 15 | def handle(self, *args, **options): 16 | if settings.DATABASES['default']['ENGINE'] != "zappa_django_utils.db.backends.s3sqlite": 17 | raise DatabaseError('This command is only for the s3sqlite Django DB engine.') 18 | else: 19 | self.stdout.write(self.style.SUCCESS('Starting database VACUUM...')) 20 | cursor = connection.cursor() 21 | cursor.execute('VACUUM;') 22 | cursor.close() 23 | self.stdout.write(self.style.SUCCESS('VACUUM complete.')) 24 | -------------------------------------------------------------------------------- /zappa_django_utils/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miserlou/zappa-django-utils/64e93f408375f181f54a00d81ec8667004142322/zappa_django_utils/migrations/__init__.py -------------------------------------------------------------------------------- /zappa_django_utils/models.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miserlou/zappa-django-utils/64e93f408375f181f54a00d81ec8667004142322/zappa_django_utils/models.py -------------------------------------------------------------------------------- /zappa_django_utils/urls.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miserlou/zappa-django-utils/64e93f408375f181f54a00d81ec8667004142322/zappa_django_utils/urls.py -------------------------------------------------------------------------------- /zappa_django_utils/views.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miserlou/zappa-django-utils/64e93f408375f181f54a00d81ec8667004142322/zappa_django_utils/views.py --------------------------------------------------------------------------------