How to prepare django app for deploying on server? - django

I followed a tutorial from a site and I deployed my django app on pythonanywhere.com.For this purpose I had to use git to upload codes.As a result my settings.py file was accessible by anybody.so any one could see my secret key on settings.py .It is not good right?
I also left DEBUG = True later I found it is not secure.Then I set DEBUG = False on my local machine and it showed it need allowed hosts.What are those things? what should I do? Where can I learn about these?

Related

Is there any way to automatically set Debug True Django application

I have a Django API that is being deployed in PythonAnywhere.
For that, I can not let the default option in settings.py as True:
DEBUG=True
However, the app also has a Swagger page using drf-yasg library. For that to work locally, I have to set the debug option as true.
However is being troublesome to maintain it, and I often mistakenly commit it as True to the repository.
Is there anyway I could manage this option so whenever I am running locally, it will automatically set it to True, but leave it as False by default?
DEBUG=False
For this purpose I use python-decouple package. To distinguish between production and development environments you can create one .env file with all production-related variables in it. In settings.py when retrieving the configuration parameters leave every default option with the one used in development. So when .env file is not present the default values are gonna be set.
from decouple import config
DEBUG = config('YOUR_ENV_VAR_DEBUG', default=True, cast=bool)
For more real-world use cases, please refer to the documentation.

Django uploading to Github, any important variables besides secret_key to keep a secret/protect?

I'm new to Django just started learning it today, since I am quite proficient in express/nodejs and mongodb, I know there are some variables that one should not push to github as they can contain passwords and other identifying information. On express/node I create a .env file and add it to my .gitignore, typically containing the password to my mongodb connection.
I am about to push my first Django api project to github and want to know if there are any other information besides the "SECRET_KEY" that I should protect. Also is .env file still the best way to protect it in Django. Furthermore I have my Django project within a ll_env-virtual environment should it make a difference.
Besides SECRET_KEY there are some other variables like:
Database credentials (PASSWORD, etc)
If hosted on any cloud providers, their secret keys (AWS_SECRET_KEY)
If using Email service, there will be your mail specific password and etc.
In short every variables that you think are to be secured should be stored in a .env file.
Also for the ease of development and production you can store Debug variable.
Basically .env file contains the individual user environment variables when collaborative working. This article by djangocentral may help you know more.

Django 400 Bad Request when run in production with gunicorn

I am getting a 400 error on all my pages when I moved my django app from one hosting service to another, the hosting service I moved to is Scalingo.
My settings.py file:
DEBUG = os.getenv("DEBUG") == "True"
ALLOWED_HOSTS = [x.strip() for x in os.getenv("ALLOWED_HOSTS").split(",")]
My env variables
ALLOWED_HOSTS="my-app.osc-fr.scalingo.fr,.localhost,127.0.0.1,[::1]"
DEBUG="False"
I contacted customer support who have advised me that it must be a configuration issue with my app.
All existing answers here I have found have advised to make sure the ALLOWED_HOSTS variable is correct, and I have already checked that it includes the required addresses according to the hosting platform's django-specific docs.
In the end I debugged the problem by doing a print(ALLOWED_HOSTS) in the settings.py file and inspecting the build logs.
Turns out the environment variables on this platform were being loaded with the quotation marks included, resulting in ['"my-app.osc-fr.scalingo.fr','.localhost','127.0.0.1','[::1]"'].
I edited the environment variables to remove the quotation marks and it works!
Not sure why the quotation marks were taken into account though, given that I can have them in on other hosting platforms and locally and they get ignored. If anyone knows I'd be interested to find out!

How to use a different database for Heroku review apps?

I have a deployment pipeline on Heroku which recently started using review apps. This means I have an app - let's call it CI-APP -- which is being created from the master branch.
Every time a pull request is made, a review app is created. We are using Django in our project and so I also added the migrate command to the release phase in the project, so that database migrations can be done automatically.
Today, a coworker submitted a pull request which contained some database changes. The problem is that the migration was ran, and since review apps seem to be using the same database as the app they are suppose to merge to, the migration was applied and now my app CI-APP stopped working...since the code base no longer matches the database structure.
I searched a lot about how to use completely different databases for the review apps compared to the parent app, but to no avail (there are some resources mentioning how you can copy db contents, but that is not what I need).
Any suggestion ?
Update
Ok, so it seems that Heroku does create a new database for the review app, however: the review app copies all of its environment variables from the parent, including the DATABASE_URL (this seems to be the only way to actually create the review app : https://s3.amazonaws.com/heroku-devcenter-files/article-images/1461071037-initial_set_up_review_apps.png)
I think I can do some black magic in the postdeploy script, but since the database generated url can be something such as HEROKU_POSTGRESQL_{color}_URL, I am not sure how to find it ....
To do that, create the app.json file at the root of your project instead of using the heroku dashboard. In this file, you can specify what environment variables to inherit from the parent.
From the heroku docs:
"env": {
"INHERIT_THIS_CONFIG_VAR": {
"required": true
},
"DONT_INHERIT_THIS_CONFIG_VAR": "production"
},
This allows you to specify which database you want to use for the review app. Looking at the documentation of the heroku postgres addon (i assume you're using postgres):
As part of the provisioning process, a DATABASE_URL config var is
added to your app’s configuration. This contains the URL your app uses
to access the database.
So the database_url config variable will be created by the adddon. You simply need to not put it in the app.json file, and it will be created automatically.
Check that you do not have the DATABASE_URL set in the Pipeline Settings CONFIG VARS in Heroku either.. if it is set there, then it seems the Review App will use that as the DB link and not the one created when the Review App is created.

How to locally test Django's Sites Framework

Django has the sites framework to support multiple web site hosting from a single Django installation.
EDIT (below is an incorrect assumption of the system)
I understand that middleware sets the settings.SITE_ID value based on a lookup/cache of the request domain.
ENDEDIT
But when testing locally, I'm at http://127.0.0.1:8000/, not http://my-actual-domain.com/
How do I locally view my different sites during development?
Create a separate settings.py file for every site, including an appropriate SITE_ID setting. Of course you can use the import statement to share common setting between files.
From now on, when running Django development server specify the --settings option to tell Django which site to run.
For example (assuming you've got two setting files - settings_first.py and settings_second.py):
manage.py runserver --settings settings_first
will run the first site, and
manage.py runserver --settings settings_second
will give you an access to the second site.
You can also run them simultaneously, specifying different ports:
manage.py runserver 8001 --settings settings_first
manage.py runserver 8002 --settings settings_second
The above commands (run on two different consoles) will make the first website accesible under http://127.0.0.1:8001/, and the second one under http://127.0.0.1:8002/
Maybe you are mislead by the documentation. You wrote:
I understand that middleware sets the settings.SITE_ID value based on a lookup/cache of the request domain.
This is not the case. It works exactly the other way around. Django uses the settings.SITE_ID value to look up the correct Site object in the database. This returns your prefered domain and site name.
The sites application was designed to fill the (in my opinion) rare usecase that you want to have multiple sites with the same database in the background. This allows you to publish the same articles on different sites but still have the flexibility that some models are available just for a single site.
For developing multiple projects (that doesn't actually make use of the sites framework) you don't have to specify anything special. You can use the default SITE_ID set to 1. For utilizing the admin's view on website links you can set in your development database the Site's domain to localhost:8000.
If you want to develop multiple sites using the same database (and make use of the sites framework) you must have each project with a distinct SITE_ID but the same database settings. The values for SITE_ID in each project on your development machine are in most cases the same as for your production servers.
FYI - I released django-dynamicsites today which has facilities to solve this issue - https://bitbucket.org/uysrc/django-dynamicsites/src