Skip to content

Commit

Permalink
Merge pull request #156 from furious-luke/chore/dockerize-example-site
Browse files Browse the repository at this point in the history
🔨 Dockerize example site
  • Loading branch information
furious-luke authored Aug 23, 2021
2 parents eb6ab25 + 3efd20f commit 41f3276
Show file tree
Hide file tree
Showing 12 changed files with 315 additions and 78 deletions.
19 changes: 19 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,22 @@ jobs:
test:
name: Test
runs-on: ubuntu-latest
strategy:
matrix:
python: [3.6, 3.9]
services:
postgres:
image: postgres
env:
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432

steps:
- name: Checkout
uses: actions/checkout@v2
Expand All @@ -32,8 +48,11 @@ jobs:
run: pip install tox

- name: Run tests
env:
DATABASE_URL: postgres://postgres:postgres@localhost/postgres
run: |
cd example_site
cp -r ../address .
tox -e py
lint:
Expand Down
18 changes: 17 additions & 1 deletion .github/workflows/test-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,20 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python: [3.5, 3.9]
python: [3.6, 3.9]
services:
postgres:
image: postgres
env:
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432

steps:
- name: Checkout
uses: actions/checkout@v2
Expand All @@ -37,8 +50,11 @@ jobs:
run: pip install tox

- name: Run tests
env:
DATABASE_URL: postgres://postgres:postgres@localhost/postgres
run: |
cd example_site
cp -r ../address .
tox -e py
lint:
Expand Down
19 changes: 19 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,22 @@ jobs:
test:
name: Test
runs-on: ubuntu-latest
strategy:
matrix:
python: [3.6, 3.9]
services:
postgres:
image: postgres
env:
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432

steps:
- name: Checkout
uses: actions/checkout@v2
Expand All @@ -32,8 +48,11 @@ jobs:
run: pip install tox

- name: Run tests
env:
DATABASE_URL: postgres://postgres:postgres@localhost/postgres
run: |
cd example_site
cp -r ../address .
tox -e py
lint:
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ media
dist/
*.egg-info/
.idea
.DS_Store
.DS_Store

.envrc
41 changes: 41 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
FROM python:3.9-slim
LABEL maintainer="[email protected]"

ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PYTHONIOENCODING=utf-8 \
LANG=C.UTF-8

RUN apt-get -qq update \
&& apt-get -y install \
bash \
locales \
git \
build-essential \
libssl-dev \
&& pip install poetry \
&& rm -rf /var/lib/apt/lists/* \
&& ln -sf /usr/share/zoneinfo/Etc/UTC /etc/localtime \
&& locale-gen C.UTF-8 || true

ARG USER_ID
ARG GROUP_ID
RUN addgroup --gid $GROUP_ID user || true \
&& useradd -M -u $USER_ID -g $GROUP_ID user || true \
&& usermod -d /code user || true

RUN mkdir -p /code
WORKDIR /code

COPY ./example_site/pyproject.toml ./example_site/poetry.lock /code/
RUN poetry config virtualenvs.create false \
&& poetry install --no-interaction --no-ansi

COPY ./example_site /code/
COPY ./address /code/address
RUN chown -R user:user /code
USER user

EXPOSE 8000

CMD ./manage.py migrate && ./manage.py runserver 0.0.0.0:8000
31 changes: 31 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
version: "3"
services:

db:
image: postgres:13-alpine
environment:
- DATABASE_URL=postgres://postgres:postgres@localhost/postgres
- POSTGRES_PASSWORD=postgres
ports:
- "5432:5432"
restart: unless-stopped

server:
build:
context: .
dockerfile: ./Dockerfile
args:
- USER_ID
- GROUP_ID
environment:
- DATABASE_URL=psql://postgres:postgres@db/postgres
- GOOGLE_API_KEY
volumes:
- ./address:/code/address
ports:
- "8000:8000"
depends_on:
- db
restart: unless-stopped
stdin_open: true
tty: true
83 changes: 49 additions & 34 deletions example_site/README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
# Overview
This is a django demonstration project that shows how `django-address` can be used to geocode manually entered postal addresses.

**The Landing Page**
This is a django demonstration project that shows how `django-address` can be used to geocode manually entered postal
addresses.

<img alt="Screenshot of landing page" src="https://user-images.githubusercontent.com/1409710/81486802-50bc4500-920c-11ea-901e-2579e7ce93b2.png" width="450">
## The Landing Page

**The Admin View**
<img alt="Screenshot of landing page"
src="https://user-images.githubusercontent.com/1409710/81486802-50bc4500-920c-11ea-901e-2579e7ce93b2.png" width="450">

<img alt="Screenshot of django admin" src="https://user-images.githubusercontent.com/1409710/81486803-52860880-920c-11ea-8938-b5e216d29c40.png" width="450">
## The Admin View

<img alt="Screenshot of django admin"
src="https://user-images.githubusercontent.com/1409710/81486803-52860880-920c-11ea-8938-b5e216d29c40.png" width="450">

## The person app and Person model
The person app is a simple implementation of a model called Person that includes an `AddressField`
and a first_name. When you geocode an address using the main landing page of this app, it saves
the name in an object with a blank first_name.

The person app is a simple implementation of a model called Person that includes an `AddressField` and a
first_name. When you geocode an address using the main landing page of this app, it saves the name in an object with a
blank first_name.

You can use Django Admin to view the saved Person objects and add a first name if you like.

### Use of `null=true` on `address` of the Person model
### Use of `null=true` on `address` of the Person model

Note that the Person model uses Address field with `null=true`.

By default, `django-address` uses Cascade delete on AddressField.
Expand All @@ -28,46 +34,55 @@ By setting `null=True`, deleting the Address associated with a Person will keep
object instance and set `address` to null.

# Setup
## Create virtual environment
* `virtualenv env`
* `source env/bin/activate`

## Install python requirements
* `pip install -r requirements.txt`

## Add Google Maps requirements
Create a Google Cloud Platform project and API Key
* Instructions for setting up an API key here: [Google Maps API Key]
* This requires the set up of a billing with Google
* The key will belong to a "project" in Google Cloud Platform

### Enable (activate) required Google Maps services for the project your key belongs to
This is hidden under Google Cloud Platform's console menu, under
**Other Google Solutions** > **Google Maps** > **APIs**. ([screenshot](https://user-images.githubusercontent.com/1409710/81484071-9d495580-91f7-11ea-891e-850fd5a225de.png))

If not already installed, [please install Docker](https://docs.docker.com/get-docker/).

Before building the example site, you will need to export three items into your environment:

```bash
export USER_ID=`id -u`
export GROUP_ID=`id -g`
export GOOGLE_API_KEY=<your-api-key>
```

The first two are used by Docker to ensure any files created are owned by your current user. The last is required to
make your Google Maps API key available to the example site. Instructions for setting up an API key here: [Google Maps
API Key]. Please note that this requires the set up of a billing account with Google.

## Enable (activate) required Google Maps services for the project your key belongs to

This is hidden under Google Cloud Platform's console menu, under **Other Google Solutions** > **Google Maps** >
**APIs**. ([screenshot](https://user-images.githubusercontent.com/1409710/81484071-9d495580-91f7-11ea-891e-850fd5a225de.png))
* Google Maps _Javascript API_
* Google Maps _Places API_

## Launch the server

### Update this example_site django project's [settings.py].
* Add your key to `GOOGLE_API_KEY` or specify `GOOGLE_API_KEY` in your environment variables.
To run the example site, simply run:

## Migrate
* `python manage.py migrate`
```bash
docker-compose up
```

This will take care of launching a database, the server, and migrating the database.

## Create a super admin to see results in Django Admin
* `python manage.py createsuperuser`

## Run server
* `python manage.py runserver`
```bash
docker-compose run --rm server python manage.py createsuperuser
```

# The Project
The page shows a simple form entry field

The page shows a simple form entry field.

### Troubleshooting Google Maps

Check the browser console on the page for javascript errors. ([Screenshot of an error](https://user-images.githubusercontent.com/1409710/81484063-90c4fd00-91f7-11ea-8833-80a346c77f89.png))
* `ApiTargetBlockedMapError`: Your API key [needs authorization](https://developers.google.com/maps/documentation/javascript/error-messages#api-target-blocked-map-error) to use the above services.
* `ApiNotActivatedMapError`: Your API key [needs Google Maps services](https://developers.google.com/maps/documentation/javascript/error-messages#api-target-blocked-map-error) to use the above services.

***NOTE:** There is up to a several minute delay in making changes to project and api key settings. New keys can also take several minutes to be recognized.


[Google Maps API Key]: https://developers.google.com/maps/documentation/javascript/get-api-key
[settings.py]: example_site/settings.py
1 change: 0 additions & 1 deletion example_site/address

This file was deleted.

9 changes: 5 additions & 4 deletions example_site/example_site/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os

import environ

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

env = environ.Env()


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/dev/howto/deployment/checklist/
Expand Down Expand Up @@ -82,10 +86,7 @@
# https://docs.djangoproject.com/en/dev/ref/settings/#databases

DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": os.path.join(BASE_DIR, "db.sqlite3"),
}
"default": env.db(),
}


Expand Down
Loading

0 comments on commit 41f3276

Please sign in to comment.