Skip to content
This repository was archived by the owner on Sep 27, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# http://editorconfig.org
# from https://github.com/pydanny/cookiecutter-django

root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[*.{py,rst,ini}]
indent_style = space
indent_size = 4

[*.{html,css,scss,json,yml}]
indent_style = space
indent_size = 2

[*.md]
trim_trailing_whitespace = false

[Makefile]
indent_style = tab

[nginx.conf]
indent_style = space
indent_size = 2
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,6 @@ ENV/

# SQLite3
db.sqlite3

# IDE
.idea/
27 changes: 16 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,24 @@

This repo is functionality complete — PR's and issues welcome!


## Prerequisites

* Python 3.4+
* Git
* Shell prompt ([Git BASH for windows](https://gitforwindows.org/) recommended for windows)


## Installation

1. Clone this repository: `git clone [email protected]:gothinkster/productionready-django-api.git`.
2. `cd` into `conduit-django`: `cd productionready-django-api`.
3. Install [pyenv](https://github.com/yyuu/pyenv#installation).
4. Install [pyenv-virtualenv](https://github.com/yyuu/pyenv-virtualenv#installation).
5. Install Python 3.5.2: `pyenv install 3.5.2`.
6. Create a new virtualenv called `productionready`: `pyenv virtualenv 3.5.2 productionready`.
7. Set the local virtualenv to `productionready`: `pyenv local productionready`.
8. Reload the `pyenv` environment: `pyenv rehash`.
1. Clone this repository: `git clone [email protected]:gothinkster/django-realworld-example-app.git`.
2. `cd` into `django-realworld-example-app`.
3. Bootstrap the environment `bin/bootstrap.sh`

Django local dev server should now be serving on port 4000

If all went well then your command line prompt should now start with `(productionready)`.

If your command line prompt does not start with `(productionready)` at this point, try running `pyenv activate productionready` or `cd ../productionready-django-api`.
#### Notes

If pyenv is still not working, visit us in the Thinkster Slack channel so we can help you out.
* `python` should be Python 3.4+, check using `python --version`. To be explicit, if on Linux/MacOS you may have a `python3.5` or `python3.6` on your path.
* If using windows use `venv\Scripts\python` instead of `venv/bin/python`
6 changes: 6 additions & 0 deletions TODO
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
TODO namespace APIs into apps/api/
TODO add tests (prefer unittest for now)
TODO rm django-extensions (not used?)
TODO marry CORS_ORIGIN_WHITELIST with ALLOW_HOSTS
TODO form opinion on dev/staging/prod settings split (perfer common.py pattern with some settings imported from ini at root)
TODO move config to root https://github.com/agconti/cookiecutter-django-rest/pull/571/files
52 changes: 52 additions & 0 deletions bin/bootstrap.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env bash
set -e # fail fast

# bootstraps to django dev server from start to finish

CWD="$(cd "$(dirname "$0")" && pwd)"
pushd $CWD/..

DJANGO_PORT='4000'

function create_venv() {
echo "Creating venv/ using system $(python3 --version) ..."
python3 -m venv venv/ --clear

echo "Upgrading packaging tools in venv..."
venv/bin/pip install --upgrade --ignore-installed pip
venv/bin/pip install --upgrade setuptools wheel
}

function install_app() {
echo "Installing conduit from setup.py ..."
venv/bin/pip install -e .
}

function migrate() {
rm -rf *.sqlite3
bin/django.sh migrate
echo "from django.contrib.auth import get_user_model; User = get_user_model(); User.objects.create_superuser('admin', '[email protected]', 'admin')" | bin/django.sh shell
}

function collectstatic() {
bin/django.sh collectstatic --link --noinput
}

function runserver() {
echo "Starting dev server, login to http://$(hostname -I | cut -d' ' -f1):${DJANGO_PORT} with [email protected]/admin"
bin/django.sh runserver 0.0.0.0:${DJANGO_PORT}
}

function main() {
create_venv
install_app
migrate
# collectstatic
runserver
}

if [ $# -eq 0 ]; then
main
elif [ $# -eq 1 ]; then
"$@" # call func by name ie. $ ./bootstrap.sh runserver
fi
7 changes: 7 additions & 0 deletions bin/django.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env bash
set -e # fail fast

CWD="$(cd "$(dirname "$0")" && pwd)"
pushd $CWD/..

venv/bin/python manage.py $1 ${@:2}
10 changes: 10 additions & 0 deletions bin/regen_requirements.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env bash
# Use this script to regenerate requirements.txt from packages installed in venv/ using pipdeptree's nice tree layout

CWD="$(cd "$(dirname "$0")" && pwd)"
pushd $CWD/..

echo "Generating new requirements.txt ..."
venv/bin/pipdeptree --local-only --freeze --exclude pip,setuptools,wheel,conduit > requirements.txt

popd
26 changes: 26 additions & 0 deletions conduit/apps/core/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from django.contrib import admin
from django.db.models.fields.related import ManyToManyField


def auto_register(model):
""" Auto-register all models incl Django and 3rd party models (obviously not for production)

Based on: http://technowhisp.com/2017/08/13/django/auto-registering-models-in-django-admin/
"""
# Get all fields from model, but exclude autocreated reverse relations and ManyToManyField
field_list = [f.name for f in model._meta.get_fields() if f.auto_created == False and not isinstance(f, ManyToManyField)]
# Dynamically create ModelAdmin class and register it.
my_admin = type('MyAdmin', (admin.ModelAdmin,),
{'list_display': field_list}
)
try:
admin.site.register(model, my_admin)
except admin.sites.AlreadyRegistered:
# This model is already registered
pass


from django.apps import apps

for model in apps.get_models():
auto_register(model)
26 changes: 25 additions & 1 deletion conduit/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"""

import os
import socket

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
Expand All @@ -25,8 +26,30 @@
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []

def get_ip():
""" Cross-platform method of getting primary internal IP
https://stackoverflow.com/a/28950776/2819573
"""
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
# doesn't even have to be reachable
s.connect(('10.255.255.255', 1))
IP = s.getsockname()[0]
except:
IP = '127.0.0.1'
finally:
s.close()
return IP

INTERNAL_IP = get_ip()

ALLOWED_HOSTS = [
INTERNAL_IP,
'.lvh.me',
'localhost',
'0.0.0.0'
]

# Application definition

Expand Down Expand Up @@ -132,6 +155,7 @@
CORS_ORIGIN_WHITELIST = (
'0.0.0.0:4000',
'localhost:4000',
INTERNAL_IP + ':4000',
)

# Tell Django about the custom `User` model we created. The string
Expand Down
10 changes: 6 additions & 4 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
Django==1.10.5
Django==1.11.14
pytz==2018.5
django-cors-middleware==1.3.1
django-extensions==1.7.1
djangorestframework==3.4.4
PyJWT==1.4.2
six==1.10.0
six==1.10.0
djangorestframework==3.8.2
pipdeptree==0.13.0
PyJWT==1.6.4
48 changes: 48 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import os

from setuptools import find_packages, setup

CWD = os.path.dirname(__file__) # FIXME __file__ is not freeze-proof

with open(os.path.join(CWD, 'README.md')) as readme:
README = readme.read()

with open(os.path.join(CWD, 'requirements.txt')) as f:
install_reqs = [
s for s in [
line.strip(' \n') for line in f
] if not s.startswith('#') and s != ''
]

# allow setup.py to be run from any path
os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))

setup(
name='conduit', # FYI this clashes with an existing package on PYPI!
version='0.1',
packages=find_packages(),
include_package_data=True,
license='BSD License', # example license
description='Example Django DRF codebase containing real world examples (CRUD, auth, advanced patterns, etc) that adheres to the RealWorld API spec.',
long_description=README,
url='https://github.com/gothinkster/realworld-example-apps',
author='Your Name',
author_email='[email protected]',
install_requires=install_reqs,
classifiers=[
'Environment :: Web Environment',
'Framework :: Django',
'Framework :: Django :: 1.11',
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Topic :: Internet :: WWW/HTTP',
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
],
)