Skip to content

Update Django Flex Example to CloudSQL v2 #616

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 25, 2016
Merged
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
101 changes: 51 additions & 50 deletions appengine/flexible/django_cloudsql/README.md
Original file line number Diff line number Diff line change
@@ -1,49 +1,46 @@
# Getting started with Django on Google Cloud Platform
# Getting started with Django on Google Cloud Platform on App Engine Flexible

This repository is an example of how to run a [Django](https://www.djangoproject.com/)
app on Google App Engine Flexible Environment. It uses the [Writing your first Django app](https://docs.djangoproject.com/en/1.9/intro/tutorial01/) as the example app to deploy.
app on Google App Engine Flexible Environment. It uses the
[Writing your first Django app](https://docs.djangoproject.com/en/1.9/intro/tutorial01/) as the
example app to deploy.


## Setup the database

This tutorial assumes you are setting up Django using a SQL database, which is the easiest way to run Django. If you have an existing SQL database running, you can use that, but if not, these are the instructions for creating a managed MySQL instance using CloudSQL.
This tutorial assumes you are setting up Django using a SQL database, which is the easiest way to
run Django.

* Create a [Second Generation CloudSQL instance](https://cloud.google.com/sql/docs/create-instance)

* Create a [CloudSQL instance](https://console.cloud.google.com/project/_/sql/create)
* Ensure the [Cloud SQL Administration API](https://console.cloud.google.com/flows/enableapi?apiid=sqladmin) is enabled.

* In the instances list, click your Cloud SQL instance.
* Install the [CloudSQL proxy](https://cloud.google.com/sql/docs/sql-proxy)

* Click Access Control.

* In the IP address subsection, click Request an IPv4 address to enable access to the Cloud SQL instance through an
IPv4 address. It will take a moment to initialize the new IP address.

* Also under Access Control, in the Authorization subsection, under Allowed Networks, click the add (+) button .
* Start the CloudSQL proxy using the connection string. The connection string can be obtained in the
instance details in the console. It's in the form of <project>:<region>:<instance-name>.

./cloud_sql_proxy -instances=[INSTANCE_CONNECTION_NAME]=tcp:3306

* In the Networks field, enter 0.0.0.0/0. This value allows access by all IP addresses.
* Create a root password

* Click Save.
`gcloud sql instances set-root-password [YOUR_INSTANCE_NAME] --password [YOUR_INSTANCE_ROOT_PASSWORD]`

Note: setting allowed networks to 0.0.0.0/0 opens your SQL instance to traffic from any computer. For production databases, it's highly recommended to limit the authorized networks to only IP ranges that need access.
* Use the root user and root password to create the `polls` database:

* Alternatively, the instance can be created with the gcloud command line tool as follows, substituting `your-root-pw
with a strong, unique password.
`mysql -h 127.0.0.1 -u root -p -e "CREATE DATABASE polls;"`

gcloud sql instances create <instance_name> --assign-ip --authorized-networks=0.0.0.0/0 set-root-password=your-root-pw
* Edit `app.yaml` to change the `cloud_sql_instances` to reflect the connection name of the
instance. This is in the form project:zone:instance

* Create a Database And User
* Optionally, use the root account to create a new MySQL user.

* Using the root password created in the last step to create a new database, user, and password using your preferred MySQL client. Alternatively, follow these instructions to create the database and user from the console.
* From the CloudSQL instance in the console, click New user.
* Enter a username and password for the application. For example, name the user "pythonapp" and give it a randomly
generated password.
* Click Add.
* Click Databases and then click New database.
* For Name, enter the name of your database (for example, "polls"), and click Add.
`mysql -h 127.0.0.1 -u root -p -e "CREATE USER 'user'@'%' IDENTIFIED BY 'password';" ``
`mysql -h 127.0.0.1 -u root -p -e "GRANT ALL PRIVILEGES ON * . * TO 'user'@'%';" ``

Once you have a SQL host, configuring mysite/settings.py to point to your database. Change `your-database-name`,
`your-database-user`, `your-database-host` , and `your-database-password` to match the settings created above. Note the
instance name is not used in this configuration, and the host name is the IP address you created.
Once you have a SQL host, configuring mysite/settings.py to point to your database. Change
`your-cloudsql-connection-string` and `your-root-password`. If you created a new user and
password, update those settings as well.

## Running locally

Expand All @@ -55,6 +52,8 @@ contains just the Django dependency.

Once the database is setup, run the migrations.

python manage.py makemigrations
python manage.py makemigrations polls
python manage.py migrate

If you'd like to use the admin console, create a superuser.
Expand All @@ -65,14 +64,30 @@ The app can be run locally the same way as any other Django app.

python manage.py runserver

Now you can view the admin panel of your local site at http://localhost:8080/admin
Now you can view the admin panel of your local site at http://localhost:8000/admin

## Deploying

Since the Django development server is not built for production, our container uses the Gunicorn server. Since Gunicorn doesn't serve static content,
the static content is instead served from Google Cloud Storage.
The app can be deployed by running

gcloud app deploy

You can view your site with:

gcloud app browse

Now you can view the admin panel of your deployed site at https://<your-app-id>.appspot.com/admin


First, make a bucket and make it publically readable, replacing <your-gcs-bucket> with a bucket name, such as your project id:
### Serving Static Files Using Cloud Storage

Since the Django development server is not built for production, our container uses the Gunicorn
server. In `mysite/urls.py`, while in DEBUG mode, Django is configured to serve static files.
However, in production, it's recommended to use Google Cloud Storage or an alternative CDN for
serving static files.

First, make a bucket and make it publically readable, replacing <your-gcs-bucket> with a bucket name
, such as your project id:

gsutil mb gs://<your-gcs-bucket>
gsutil defacl set public-read gs://<your-gcs-bucket>
Expand All @@ -89,31 +104,17 @@ Now your static content can be served from the following URL:

http://storage.googleapis.com/<your-gcs-bucket/static/

Make sure to replace <your-cloud-bucket> within `mysite/settings.py` to set STATIC_URL to the correct value to serve static content from, and
uncomment the STATIC_URL to point to the new URL.

The app can be deployed by running

gcloud app deploy

which deploys to version 1, and `promote` makes version 1 the default version.

Now you can view the admin panel of your deployed site at https://<your-app-id>.appspot.com/admin.
Make sure to replace <your-cloud-bucket> within `mysite/settings.py` to set STATIC_URL to the
correct value to serve static content from, and uncomment the STATIC_URL to point to the new URL.

### Production

Once you are ready to serve your content in production, there are several
changes required for the configuration. Most notable changes are:

* Use Google Cloud Storage or a CDN to serve static files
* Add ".appspot.com" to your `ALLOWED_HOSTS`
* Change the `DEBUG` variable to `False` in your settings.py file.
* If you are using a Cloud SQL database
instance, in order to change from `DEBUG = True`
to `DEBUG = False` you will need to properly configure the database. See
instructions
[here](https://cloud.google.com/sql/docs/app-engine-connect#gaev2-csqlv2) and be
sure to change your `app.yaml` file as well as the `HOST` key in your
`DATABASES` object.


## Contributing changes

Expand Down
3 changes: 3 additions & 0 deletions appengine/flexible/django_cloudsql/app.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ runtime: python
vm: true
entrypoint: gunicorn -b :$PORT mysite.wsgi

beta_settings:
cloud_sql_instances: <your-cloudsql-connection-string>

runtime_config:
python_version: 3
# [END runtime]
Expand Down
15 changes: 10 additions & 5 deletions appengine/flexible/django_cloudsql/mysite/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,18 @@
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': '<your-database-name>',
'USER': '<your-database-user>',
'PASSWORD': '<your-database-password>',
'HOST': '<your-database-host>',
'PORT': '3306',
'NAME': 'polls',
'USER': 'root',
'PASSWORD': '<your-root-password>',
}
}
# In the flexible environment, you connect to CloudSQL using a unix socket.
# Locally, you can use the CloudSQL proxy to proxy a localhost connection
# to the instance
DATABASES['default']['HOST'] = '/cloudsql/<your-cloudsql-connection-string>'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't you have to separate database configs local and live and tell django to switch between them?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If by different database configs you mean not have them both on default, you could, but then all your code and management commands have to specify the database, which I don't think is what you want for local vs production, because all the code would probably just point to some settings flag and it's a lot of code that accomplishes nothing. I think the feature is more for cases where in production there's multiple databases. If by different database configs you mean just totally separate dict objects that we pick here, it's just a readability preference. Since the configs are the same except for a single line, I thought this was easiest, you don't have to type in the password in two places, etc.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha, then this is fine.

if os.getenv('GAE_APPENGINE_HOSTNAME'):
else:
DATABASES['default']['HOST'] = '127.0.0.1'
# [END dbconfig]

# Internationalization
Expand Down
9 changes: 9 additions & 0 deletions appengine/flexible/django_cloudsql/mysite/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@

from django.conf.urls import include, url
from django.contrib import admin
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.conf import settings

urlpatterns = [url(r'^', include('polls.urls')),
url(r'^admin/', admin.site.urls)]


# This enables static files to be served from the Gunicorn server
# In Production, serve static files from Google Cloud Storage or an alternative
# CDN
if settings.DEBUG:
urlpatterns += staticfiles_urlpatterns()