Heroku app.json set default django admin password - python

I'm trying to add a depoly to heroku button and I followed their examples and all and ended up with the following app.json for my django app
{
"name": "foo",
"description": "foo website",
"repository": "https://github.com/foo/bar",
"keywords": ["python", "django", "foobar"],
"env": {
"DJANGO_SECRET_KEY": {
"description": "A randomly generated secret to secure your Django installation",
"generator": "secret"
}
},
"scripts": {
"postdeploy": "sh -c 'python manage.py syncdb --noinput; python manage.py migrate --noinput'"
}
}
Doing the syncdb will create the auth tables and so on, but what I need is to allow the user who wants to deploy the app to specify the default admin username and password. I realize that doing heroku run python manage.py syncdb will prompt the user if we wants to create a superuser, but that's not exactly what I need. I need it to be configured from Heroku's dashboard when a user clicks on the button. I want this to allow non technical people to still be able to deploy the app without going through the terminal and all. Is there any way of doing this?

After some research, I managed to do what I wanted and thought I'd share it. I was able to do it using django-extensions. I made a python script
# create_admin.py
import os
if "ADMIN_USER" in os.environ and "ADMIN_PASSWORD" in os.environ:
from django.contrib.auth.models import User
user=User.objects.create_user(os.environ['ADMIN_USER'], password=os.environ['ADMIN_PASSWORD'])
user.is_superuser=True
user.is_staff=True
user.save()
and changed the scripts part of my app.json
"scripts": {
"postdeploy": "sh -c 'python manage.py syncdb --noinput; python manage.py migrate --noinput; python manage.py runscript create_admin'"
}
make sure you read django-extensions docs for more information on where to place the scripts and how to python manage.py runscript.
IMPORTANT: you may want to go to herkou's configs page and remove the environment variables after you run the script.

Related

Debugging dockerized Django in VS Code results in error "Timed out waiting for launcher to connect"

I want to debug my Django application using a docker container in Visual Studio Code.
Microsoft published a guide how to do that, which I followed step by step:
https://code.visualstudio.com/docs/containers/quickstart-python
But when I try to run the debugger, I get the following error message:
Timed out waiting for launcher to connect
Here is what I did step by step:
I initialized a simple Django application using django-admin startproject helloworld
In VS Code I opened the folder including the manage.py
Opened Command Palette Ctrl + Shift + P, and then selected Docker: Add Docker Files to Workspace...
Select Application Platform Python: Django
Include Docker Compose files No
Relative path to the app's entrypoint manage.py
What ports does your app listen on? 8000
VS Codes then creates several files (see below).
When I try to start the debugger (like in the guide), I get the following error message:
The terminal doesn't show any error messages, but the commands executed:
.vscode/launch.json:
{
"configurations": [
{
"name": "Docker: Python - Django",
"type": "docker",
"request": "launch",
"preLaunchTask": "docker-run: debug",
"python": {
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "/app"
}
],
"projectType": "django"
}
}
]
}
.vscode/tasks.json:
{
"version": "2.0.0",
"tasks": [
{
"type": "docker-build",
"label": "docker-build",
"platform": "python",
"dockerBuild": {
"tag": "dockerdebugging:latest",
"dockerfile": "${workspaceFolder}/Dockerfile",
"context": "${workspaceFolder}",
"pull": true
}
},
{
"type": "docker-run",
"label": "docker-run: debug",
"dependsOn": [
"docker-build"
],
"python": {
"args": [
"runserver",
"0.0.0.0:8000",
"--nothreading",
"--noreload"
],
"file": "manage.py"
}
}
]
}
Dockerfile:
# For more information, please refer to https://aka.ms/vscode-docker-python
FROM python:3.8-slim-buster
EXPOSE 8000
# Keeps Python from generating .pyc files in the container
ENV PYTHONDONTWRITEBYTECODE 1
# Turns off buffering for easier container logging
ENV PYTHONUNBUFFERED 1
# Install pip requirements
ADD requirements.txt .
RUN python -m pip install -r requirements.txt
WORKDIR /app
ADD . /app
# Switching to a non-root user, please refer to https://aka.ms/vscode-docker-python-user-rights
RUN useradd appuser && chown -R appuser /app
USER appuser
# During debugging, this entry point will be overridden. For more information, please refer to https://aka.ms/vscode-docker-python-debug
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "helloworld.wsgi"]
requirements.txt:
# To ensure app dependencies are ported from your virtual environment/host machine into your container, run 'pip freeze > requirements.txt' in the terminal to overwrite this file
django==3.0.3
gunicorn==20.0.4
VS Code Version: 1.47.1
Python Extension Version: v2020.7.94776
The idea of debugging in vs code is to:
use debugpy to launch your code with a port, say 5678
in vscode to 'Remote Attach' to that process.
I may be wrong but what i can see from your code, you didn't attach to your process.
I wrote the way I did here, I use docker-compose and docker. My way is different with yours but you will get the idea...:)
My issue were missing packages. Docker usually works fine, I haven't had any issues before at all.
I originally installed docker like described in the official documentation:
https://docs.docker.com/engine/install/ubuntu/
But after I tried installing the docker.io package, debugging worked fine in VS Code:
sudo apt install docker.io
There's no errors compared to the vscode tutorial in your project. Cause the error is timeout waiting for luncher to connect, try restart docker service and reload your window in vscode.
Here is a clue and a workaround:
The instructions I followed had me open VS code inside my ubuntu WLS2 instance. Note: my app is just a generic python app, not django.
If I click this and change it to open as a windows folder, then fun debug, everything suddenly works for me. (It spins up the docker and connects to it with debug, does breakpoints etc.)
I think what is happening for me is that "sometimes" docker is starting the container/app on its own WSL instance and my ubuntu instance cannot route to it for the debug.
I say sometimes, because sometimes it works. I think it might be related to which application (docker, ubuntu, vscode) I start first when I boot my machine.
I've messed with the docker, resources, WSL integration settings, the windows firewall, and restarted various things.
I'm sure a proper fix is not that complicated, however running VS code in native windows is enough of a fix for me. I don't see why the added complexity of starting the VS code session inside WSL is actually necessary.

Project created using cookiecutter-django not running

Its been a few months that I am trying to learn Django. In the same process (and while reading "Two Scoops of Django 1.11"), I came across Cookiecutter Django. It has helped me learn a few important things to keep in mind while creating a project.
I tried to run the template provided by cookiecutter-django but failed. Here are the steps that I followed.
Create a virtual environment named test and activate it.
mkvirtualenv test
Installed Cookiecutter.
pip install coockiecutter
Installed Cookiecutter Django, The project name was set to "Test Project" and other defaults settings were chosen. I am using PostgreSQL 9.6.
cookiecutter https://github.com/pydanny/cookiecutter-django
Create a database named "test_project" in PostgreSQL.
Run python manage.py migrate
The result was the error:
django.db.utils.OperationalError: FATAL: role "dev" does not exist
I have also tried making a user named test_project_user and granting it all the privileges to test_project database. I am still getting the same error.
The problem seems to be that you specified a database user that does not exist (or you left blank and it assumes your system user), in:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'test_project',
'USER': 'HERE', # Set test_project_user here
...
}
}

Django does not install model tables

In my project, I have a routers.py with different router classes. Now, I am making a new app. I have created my models.py. I have also registered the app in the INSTALLED_APPS in settings.py. Then, I ran validate. Everything is fine. When I syncd thoughb, Django does not install the tables. I tried using
python manage.py sqlall <app_name> | psql <database>
Then, I get an error message saying:
psql: FATAL: password authentication failed for user <user name>
I noticed that the role does not exist in postgres. So, I created the role with login privilege createdb and password. Then, I get a different error message:
psql: FATAL: password authentication failed for user <user name>
close failed in file object destructor:
Error in sys.excepthook:
Original exception was:
And, it does not provide the original exception.
Any help is much appreciated.
It looks like the Django application is unable to log onto the DB.
In django's settings.py make sure you have the proper DB credentials setup:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'HOST': get_env_variable("DJANGO_DB_HOST"),
'NAME': get_env_variable("DJANGO_DB_NAME"),
'USER': get_env_variable("DJANGO_DB_USER"),
'PASSWORD': get_env_variable("DJANGO_DB_PWD"),
'PORT': '',
},
...
}
As you can see my credentials are grabbed from environment variables. You can hardcode them in for test purposes.
Then in the DB (mine is postgresql) create the user/grant it the correct privileges, for example:
ssh root#dbhost
su - postgres
createdb dbname
psql
GRANT ALL PRIVILEGES ON DATABASE dbname TO dbuser
That should do.
I recommend the following steps as well, if they are missing from your setup:
In your app's admin.py register your models with Django's admin:
# Register your models here.
admin.site.register(Model1)
...
admin.site.register(ModelN)
Then, assuming you have created the project already, run:
python manage.py migrate
(it's the syncdb equivalent. Read the docs about migrations).
If that command does not ask for the admin superuser then create your administrative user (i.e. the user who can manipulate the models through django's admin interface) with:
python manage.py createsuperuser
Fire up Django
python manage.py runserver 0.0.0.0:8000
and see what happens whan you visit your site and admin at
localhost:8000/
localhost:8000/admin
Please pardon me if you know all those things already. That is what I normally do in my dev environment (I also use virtualenv, of course).

"no such table" error on Heroku after django syncdb passed

I'm trying to deploy my Django application to Heroku. The migrations are in my local Git. When I try:
git push heroku master
heroku run python manage.py syncdb
It applies the migrations and also promts me to create superuser, which I successfully do. Now the application is up and running, however when I try to log into the Django admin it's throwing:
OperationalError no such table: user_user
When I try
heroku run python manage.py makemigrations
heroku run python manage.py migrate
heroku run python manage.py createsuperuser
It applies all migrations, but fails to create superuser throwing:
django.db.utils.OperationalError: no such table: user_user
Either way I can not have my database set up and migrated on Heroku.
My database settings are:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
My user model is:
class User(AbstractUser):
rating = models.PositiveIntegerField(default=settings.DEFAULT_USER_RATING)
Django version is 1.7.1.
How do I get my database tables created on Heroku?
You must not use sqlite3 on Heroku.
sqlite stores the database as a file on disk. But the filesystem in a Heroku dyno is not persistent, and is not shared between dynos. So, when you do heroku run python manage.py migrate, Heroku spins up a new dyno with a blank database, runs the migrations, then deletes the dyno and the database. The dyno that's running your site is unaffected, and never gets migrated.
You must use one of the Heroku database add-ons. There is a free tier for Postgres. You should use the dj-database-url library to set your database settings dynamically from the environment variables which Heroku sets.
Also, for the same reason, you must do manage.py makemigrations locally, commit the result to git, then push to Heroku.
You can use postgresql:
In settings.py add(at the end of file):
# ie if Heroku server
if 'DATABASE_URL' in os.environ:
import dj_database_url
DATABASES = {'default': dj_database_url.config()}
In requirements.txt add:
dj-database-url
psycopg2
Now you can run:
heroku run python manage.py migrate
pip install django-heroku
Add import django_heroku at top of file settings.py
Place django_heroku.settings(locals()) at the very bottom of settings.py
It will automatically configure your db. You can learn more on their website
What version of django you are using..?
If you are using django>=1.7 you need to run migrate
After adding models you need to do
python manage.py makemigrations then python manage.py migrate
If your project already contain migrations you can directly run python manage.py migrate command.
If you miss any step mentioned above please do that.

How is python manage.py createsuperuser useful?

I am a new in Django. I have found this piece of code
python manage.py createsuperuser
How is this useful? In what kind of situation is it necessary?
From the django-docs (emphasis mine):
This command is only available if Django’s authentication system (django.contrib.auth) is installed.
Creates a superuser account (a user who has all permissions). This is useful if you need to create an initial superuser account or if you need to programmatically generate superuser accounts for your site(s).
When run interactively, this command will prompt for a password for the new superuser account. When run non-interactively, no password will be set, and the superuser account will not be able to log in until a password has been manually set for it.
python manage.py createsuperuser
in addition to mu's answer, superuser is the one who can log into admin page and who can have permissions to add, edit, delete objects in thru admin page.
Whenever you wipe your database or deploy to a server you often want to be able to setup up an "admin" account to be able to log into the /admin/ interface like this:
python manage.py createsuperuser -u admin -e admin#example.com --noinput
python manage.py changepassword admin
Unfortunately, usually you want your deployments to be automatic and as #mu pointed out you still must interactively set the password. However, you can just add the record to the database yourself if you want to automate the process:
echo "from django.contrib.auth.models import User" > createadmin.py
echo "User.objects.create_superuser('dan', 'dan#email.io', 'pass')" >> createadmin.py
python manage.py shell < createadmin.py
Of course don't forget to set your password to something other than 'pass'.
#hobs thanks for this awesome answer. it pointed me in the right direction with regards to finding an ultimate answer that worked for me. Below is my working config, the only difference is I modified the User import for newer versions of Django
from django.contrib.auth import get_user_model
User = get_user_model()
User.objects.create_superuser('adminuser', 'dev#email.io', 'password')
and the command I run is;
python3 manage.py shell < /opt/admin.py
I needed this for a Dockerfile config and below is how the line looks in Dockerfile line
RUN \
python3 ./manage.py migrate && \
python3 manage.py shell < adminuser.py
thanks again and hopefully someone else finds this useful

Categories