django problem with shared memcache nodes - django

i have two django instances running on two servers and i am using memcached to cache some data in my applicationa.
each server have it's own memcached installed, i want to both of my applications have access to both caches but i cant't. when i set a values from one application in cache other application cant access it
my memcached instances are running as root, also i have tried memcache and other users but it didn't fix the problem.
for testing i used django shell, import cache class:
from django.core.cache import cache
set a value in cache :
cache.set('foo', 'bar', 3000)
and tried to get value from my other Django instance :
cache.get('foo')
but it returns nothing!
here is my settings.py file :
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
'LOCATION': [
'first app server ip:port',
'second app server ip:port']
}
}
and my memcached.conf(comments deletede):
-d
logfile /var/log/memcache/memcached.log
# -v
-vv
-m 512
-p 11211
-u root
-l 192.168.174.160
# -c 1024
# -k
# -M
# -r
-P /var/run/memcached/memcached.pid

The order of location in settings must be the same in all servers. Could you please check if they are same?

Related

Troubleshooting access to Flask app in Vagrant guest

I have a toy Flask app:
from flask import Flask
app = Flask(__name__)
#app.route("/home")
def home():
return "<h1>Home...</h1>"
#app.route("/health")
def health():
return "<h1>Healthy</h1>"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000, debug=True)
.. which is being provisioned using Ansible on a Vagrant guest machine with the following Vagrantfile:
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure(2) do |config|
config.vm.box = "geerlingguy/centos7"
config.vm.provision "ansible_local" do |ansible|
ansible.playbook = "playbooks/run.yml"
ansible.tags = "install"
end
config.vm.network "forwarded_port", guest: 5000, host: 5000
config.vm.provider "virtualbox" do |v|
v.memory = 2048
v.cpus = 1
end
end
If I vagrant ssh to the guest and launch the flaskapp in with the following:
export FLASK_APP='/flaskapp/app.py'
export FLASK_ENV='development'
cd /flaskapp
python3 -m flask run
I can curl 127.0.0.1:5000/home with a successful response.
However from the Vagrant host (i.e. not the guest where the flask app is running), I cannot access http://localhost:5000/home. Accessing localhost:5000/home (or 127.0.0.1:500/home) is:
The connection was reset
The connection to the server was reset while the page was loading.
The site could be temporarily unavailable or too busy. Try again in a few moments.
If you are unable to load any pages, check your computer’s network connection.
If your computer or network is protected by a firewall or proxy, make sure that Firefox is permitted to access the Web.
I'm using Windows 10, and the guest VMs network config looks like this:
I have tried assigning static ip or assigning an ip dynamically but I cannot access. I am not sure if it's something that I need to add to the /etc/hosts file...
Can anyone help to identify the issue here and how can I debug this kind of problem?

Deploying an Angular 4 frontend with a Django Rest Framework backend on Heroku

I have built the front end using Angular 4 (using the angular CLI) and the backend using Django and the Django Rest Framework.
The development environment is set up in such a way that the static assets, HTML,JS etc are all part of the Angular app. The angular app runs on a server spun up by the CLI at localhost:4200 and and it communicates with the rest framework backend through a series of HTTP calls through CORS to the DRF API which is live at another localhost:8000 only to obtain and serve information.
How do I go about deploying this as a production-ready application on Heroku? The heroku guides illustrate how to deploy a Django app separately or an Angular app separately (running on a node server). Do i deploy them as two separate instances or do I combine them. If so , how do I go about doing that?
This solution doesn't match the request of how to do this on Heroku, but is done at request of #pdfarhad.
So first about what I used to host, my domain name was registered with Godaddy, and that pointed to a server (droplet) I created at Digitalocean. Noting that the DNS servers on godaddy were pointing to digitaloceans, ns1.digitalocean.com, ns2.digitalocean.com and ns3.digitalocean.com. Then on digitalocean, on the networking tab, created two A records that both point to the server I created, one being example.com, and the other being api.example.com.
With that done, when you create a new droplet, the password for the root user will be emailed, then do:
# ssh root#<IPADDRESSOFSERVER>
# sudo apt-get update
# sudo adduser jupiar
# sudo usermod -aG sudo jupiar
# su - jupiar
$ sudo apt-get install nginx
At this point, you should be able to navigate to your IPADDRESS and see the nginx landing page, you might have to wait a while for godaddy and digitalocean to pass typing example.com, I think half a day passed until the name servers were all synced up and stuff.
Now, I just set up passwordless ssh, on my local machine:
$ ssh-keygen (no passphrase)
$ cat ~/.ssh/id_rsa.pub (then copy this)
And now on the server:
$ mkdir ~/.ssh
$ chmod 700 ~/.ssh
$ nano ~/.ssh/authorized_keys (paste the rsa you copied)
$ chmod 600 ~/.ssh/authorized_keys
$ sudo nano /etc/ssh/sshd_config
| Make sure:
| PasswordAuthentication no
| PubkeyAuthentication yes
| ChallengeResponseAuthentication no
$ sudo systemctl reload sshd
$ exit
Now you should be able to ssh into your server without a password.
I use anaconda python because I do alot of datascience, so:
$ wget https://repo.continuum.io/archive/Anaconda3-5.0.0.1-Linux-x86_64.sh
$ bash https://repo.continuum.io/archive/Anaconda3-5.0.0.1-Linux-x86_64.sh
| installed to /home/jupiar/anaconda3, auto append path to .bashrc
$ . .bashrc
$ source .bashrc
Now, because in the past I had some trouble with running linux supervisor with python virtualenvs, I just install everything globally. uwsgi is mostly in C, so you need some packages so as to compile it.
$ sudo apt-get install build-essential python-dev python3-dev
$ pip install uwsgi
Now, making a git repository, you can make one on the server, but i prefer to use github, because it provides alot of useful tools, and a good place to collaborate between contributers on the project, so make a private repository on github, then on your local machine: (the third line is because I use Mac)
MAKE A NEW FOLDER, and put everything in there
$ echo "# example" >> README
$ git init
$ find . -name .DS_Store -print0 | xargs -0 git rm -f --ignore-unmatch
$ echo ".DS_Store" >> .gitignore
$ git add .
$ git commmit -m "first commit"
$ git remote add origin https://github.com/<GITUSERNAME>/<REPONAME>.git
$ git push -u origin master
so, again on the local machine, set up a new angular 4 app with scss styling and skipping making it a git repo, because it wont show properly on github, repo inside repo etc... :
$ ng new frontend --style=scss --skip-git
And, we will keep the app as it is for now, just remember the server will need a dist folder, and you can do something like this in the frontend folder, using ahead-of-time...:
$ ng build --aot -prod
Now on local machine again, create the Django Rest Framework backend:
$ conda create -n exampleenv python=3.6 anaconda
$ source activate exampleenv
(exampleenv)$ pip install django
(exampleenv)$ pip install djangorestframework
(exampleenv)$ pip install django-cors-headers
(exampleenv)$ django-admin startproject backend
(exampleenv)$ cd backend
(exampleenv)$ django-admin startapp api
(exampleenv)$ python manage.py migrate
(exampleenv)$ python manage.py createsuperuser
Now, just to get a minimal rest framework to work, we need to:
In settings.py add to INSTALLED APPS:
'rest_framework',
'corsheaders',
'api',
In settings.py add to top of MIDDLEWARE:
'corsheaders.middleware.CorsMiddleware',
In settings.py add:
CORS_ORIGIN_ALLOW_ALL = True
In settings.py add:
ALLOWED_HOSTS = ['<DIGITALOCEANSERVER-IP>', '*', 'localhost', '127.0.0.1']
in backend/urls.py:
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api/', include('api.urls')),
]
in api/models.py:
from django.db import models
# Create your models here.
class testModel(models.Model):
word = models.CharField("word", max_length=20)
in api/serializers.py:
from rest_framework import serializers
from .models import testModel
class testSerializer(serializers.ModelSerializer):
word = serializers.CharField(max_length=20)
class Meta:
model = testModel
fields = ('id', 'word')
in api/urls.py:
from django.conf.urls import url, include
from rest_framework.urlpatterns import format_suffix_patterns
from .views import testView
urlpatterns = [
url(r'^test/', testView.as_view()),
]
in api/views.py:
from rest_framework import generics
from rest_framework import status
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import AllowAny
from django.shortcuts import render
from .models import testModel
from.serializers import testSerializer
# Create your views here.
class testView(APIView):
def get(self, request):
return Response({'succeded?', 'yes'})
Now with all that saved, it should work if you:
(exampleenv)$ python manage.py runserver
navigate to :8000/api/test/
With both an angular 4 frontend and DRF backend done, we can push the changes to github, by now that will be a LOT of changes ;)
Now, lets get our frontend and backend onto the server, log into the server and good idea now is to add the ssh keys from your server (and local machine) if you havnt already, to github. On the server we can do this via:
$ ssh-keygen -t rsa -b 4096 -C "<EMAIL ADDRESS>"
$ eval "$(ssh-agent -s)"
Agent pid ....
$ ssh-add ~/.ssh/id_rsa
Enter passphrase for /home/jupair/.ssh/id_rsa:
Identity added: /home/jupiar/.ssh/id_rsa (/home/jupiar/.ssh/id_rsa)
$ mkdir example
$ cd example
$ git init
$ git pull git#github.com:<GITHUBUSERNAME>/<REPONAME>.git
(At some point here, you might have errors with using https or ssh) if you are using ssh keys, you need to use the ssh repo name from github (on github, the clone or download button will give you these links), and on the local machine too you may need to set-url to use the ssh name):
[on local machine]
$ git remote set-url origin git#github.com:<GITHUBUSERNAME>/<REPONAME>.git
Okay, now on your server, you should have the frontend and backend folders in your project folder, angular is very easy, on the server:
$ cd /etc/nginx/sites-available
$ sudo rm default
$ sudo nano frontend.conf
and place something like this inside:
server {
listen 80;
listen [::]:80;
root /home/jupiar/example/frontend/dist;
index index.html index.htm index.nginx-debian.html;
server_name example.com;
location / {
try_files $uri $uri/ =404;
}
}
Now we need to link that file into sites enabled:
$ sudo ln -s /etc/nginx/sites-available/frontend.conf /etc/nginx/sites-enabled/frontend.conf
$ cd /etc/nginx/sites-enabled
$ sudo rm default
$ sudo systemctl restart nginx.service
Heading over to example.com we should now see the angular app working,
Okay, now to make the backend servable, is a little bit more tricky:
$ cd /etc/nginx/sites-available
$ sudo nano backend.conf
and place something like this:
server {
listen 80;
listen [::]:80;
server_name api.example.com;
location /static/admin {
alias /home/jupair/anaconda3/lib/python3.6/site-packages/django/contrib/admin/static/admin;
}
location /static/rest_framework {
alias /home/jupiar/anaconda3/lib/python3.6/site-packages/rest_framework/static/rest_framework;
}
location / {
proxy_pass http://127.0.0.1:9000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
}
}
Now, link that file to sites-enabled:
$ sudo ln -s /etc/nginx/sites-available/backend.conf /etc/nginx/sites-enabled/backend.conf
Now to set up superviser to use uwsgi to start the django app
$ sudo apt-get install supervisor
$ sudo nano /etc/supervisor/conf.d/backend_api.conf
And inside, have something like:
[program:backend_api]
command = /home/jupiar/anaconda3/bin/uwsgi --http :9000 --wsgi-file /home/jupiar/example/backend/backend/wsgi.py
directory = /home/jupiar/example/backend
user = jupiar
autostart = true
autorestart = true
stdout_logfile = /var/log/backnd_api.log
stderr_logfile = /var/log/backend_api_err.log
Now, you will need to run:
$ sudo supervisorctl reread
$ sudo supervisorctl update
$ sudo supervisorctl restart backend_api
$ sudo systemctl restart nginx.service
Now, heading over to api.example.com/api/test/ should give you the django rest framework response of suceeded: true.
From now on, you can just use a custom shell script whenever you want to make changes live, that would be like:
cd /home/jupiar/example
git reset --hard (sometimes you may need to run this)
git pull git#github.com/<GITUSERNAME>/<PROJECTNAME>.git
sudo supervisorctl restart backend_api
sudo systemctl restart nginx.service
And thats pretty much it, I believe everything is there from how I remember doing it, any questions or if something is wrong/doesn't work for you, please comment and let me know :)

Django channels times out with daphne and worker

I have a problem with django channels.
My Django app was running perfectly with WSGI for HTTP requests.
I tried to migrate to channels in order to allow websocket requests, and it turns out that after installing channels and running ASGI (daphne) and a worker, the server answers error 503 and the browser displays error 504 (time out) for the http requests that were previously working (admin page for example).
I read all the tutorial I could find and I do not see what the problem can be. Moreover, if I run with "runserver", it works fine.
I have an Nginx in front of the app (on a separate server), working as proxy and loadbalancer.
I use Django 1.9.5 with asgi-redis>=0.10.0, channels>=0.17.0 and daphne>=0.15.0. The wsgi.py and asgi.py files are in the same folder. Redis is working.
The command I was previously using with WSGI (and which still works if I switch back to it) is:
uwsgi --http :8000 --master --enable-threads --module Cats.wsgi
The command that works using runserver is:
python manage.py runserver 0.0.0.0:8000
The commands that fail for the requests that work with the 2 other commands are:
daphne -b 0.0.0.0 -p 8000 Cats.asgi:channel_layer
python manage.py runworker
Other info:
I added 'channels' in the installed apps (in settings.py)
other settings.py relevant info
CHANNEL_LAYERS = {
"default": {
"BACKEND": "asgi_redis.RedisChannelLayer",
"ROUTING": "Cats.routing.app_routing",
"CONFIG": {
"hosts": [(os.environ['REDIS_HOST'], 6379)],
},
},
}
Cats/routing.py
from channels.routing import route, include
from main.routing import routing as main_routing
app_routing = [
include(main_routing, path=r"^/ws/main"),
]
main/routing.py
from channels.routing import route, include
http_routing = [
]
stream_routing = [
route('websocket.receive', 'main.consumers.ws_echo'), #just for test once it will work
]
routing = [
include(stream_routing),
include(http_routing),
]
main/consumers.py
def ws_echo(message):
message.reply_channel.send({
'text': message.content['text'],
})
#this consumer is just for test once it will work
Any idea what could be wrong? All help much appreciated! Ty
EDIT:
I tried a new thing:
python manage.py runserver 0.0.0.0:8000 --noworker
python manage.py runworker
And this does not work, while python manage.py runserver 0.0.0.0:8000 was working...
Any idea that could help?
channels will use default views for un-routed requests.
assuming you use the javascripts right, I suggest you use only your default Cats/routing.py file as following:
from channels.routing import route
from main.consumers import *
app_routing = [
route('websocket.connect', ws_echo, path="/ws/main")
]
or with reverse to help with your path
from django.urls import reverse
from channels.routing import route
from main.consumers import *
app_routing = [
route('websocket.connect', ws_echo, path=reverse('main view name'))
]
I think also your consumer should be changed. when browser connects using websockets the server should first handle adding message reply channel. something like:
def ws_echo(message):
Group("notifications").add(message.reply_channel)
Group("notifications").send({
"text": json.dumps({'testkey':'testvalue'})
})
the send function should probably be called up on different event and the "notifications" Group should probably changed to have a channel dedicated to the user. something like
from channels.auth import channel_session_user_from_http
#channel_session_user_from_http
def ws_echo(message):
Group("notify-private-%s" % message.user.id).add(message.reply_channel)
Group("notify-private-%s" % message.user.id).send({
"text": json.dumps({'testkey':'testvalue'})
})
If you're using heroku or dokku make sure you've properly set the "scale" to include the worker process. By default they will only run the web instance and not the worker!
For heroku
heroku ps:scale web=1:free worker=1:free
For dokku create a file named DOKKU_SCALE and add in:
web=1
worker=1
See:
http://blog.codelv.com/2017/10/timouts-django-channels-on-dokku.html
https://blog.heroku.com/in_deep_with_django_channels_the_future_of_real_time_apps_in_django

django production environment is using the wrong db

I am writing my first 'self-made deployment'. Writing the deploy script using fabric. I have added an export to .bashrc on my production machine to export a key:value {'DIGITAL_OCEAN': True} so I can add some conditions in my settings to use databases based on local or production environments.
SETTINGS.PY
import os
if 'DIGITAL_OCEAN' in os.environ:
ON_DO = True
else:
ON_DO = False
if ON_DO:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'user',
'USER': 'user',
'PASSWORD': 'pass',
'HOST': 'localhost',
'PORT': '',
}
}
else:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'localuser',
'USER': 'localuser',
'PASSWORD': 'localpass',
'HOST': 'localhost',
'PORT': '',
}
NOW... If I run an ssh command like '$ python manage.py migrate' all goes well ON_DO is discovered and it goes well, but in my deploy script, listed below, ON_DO comes through as false, I had this happen spontaneously before and then it corrected itself (maybe with a gunicorn or nginx restart) so I tried adding some restarts to the script, but no luck so far and I am out of ideas.
def server():
'''IDK'''
env.host_string = 'ip.ip.ip.ip'
env.user = 'root'
def pull_deploy():
'''Makes the server pull it from git repo at bitbucket'''
path = '/home/django/'
print(red('BEGINNING PULL DEPLOY'))
with cd('%s' % path) :
run('pwd')
print(green('Pulling Master from Bitbucket'))
run('git pull origin master')
print(green('SKIPPING installing requirements'))
run('source %spyenv/bin/activate && pip install -r langalang/requirements.txt' % path)
print('Collecting static files')
run('source %spyenv/bin/activate && python langalang/manage.py collectstatic' % path)
print('Restarting Gunicorn')
run('sudo service gunicorn restart')
print('Restarting Nginx')
run('nginx -s reload')
print('Making migrations')
run('source %spyenv/bin/activate && python langalang/manage.py makemigrations' % path)
print('Migrating DB')
run('source %spyenv/bin/activate && python langalang/manage.py migrate' % path)
print('Restarting Gunicorn')
run('sudo service gunicorn restart')
print('Restarting Nginx')
run('nginx -s reload')
print(red('DONE'))
The problem was that I had declared my environment variable 'ON_DO' in ~.bashrc or ~.profile and those only export the variable from a login shell. I guess django doesn't count as a login shell when it runs by itself. I had to export them from the .wsgi file in django itself.
That file only runs in production as far as I can tell so it only outputs the variables to the production system.
#deltaskelta Why would you set the variable in wsgi.py file? Doesn't it defeat the purpose as this variable will also be set in your development environment.
Here is the shell script that I wrote.
#!/bin/sh
ps aux | grep usr/bin/[p]ython
if [ $? != 0 ]
then
export UNIQUE_KEY='value'
python ~/project_name/manage.py runserver 0:8000
exit 0
else
exit 1
fi
What this does is, sets the UNIQUE_KEY environment variable whenever it executes and unsets it as soon as it stops. Moreover, it works with crontab as well. This works because shell scripts executed via crontab are run in a non-interactive non-login shell session.
Probably an in-depth understanding of distinct shell sessions would help.
The Difference between Login, Non-Login, Interactive, and Non-Interactive Shell Sessions
The bash shell reads different configuration files depending on how the session is started.
One distinction between different sessions is whether the shell is being spawned as a "login" or "non-login" session.
A login shell is a shell session that begins by authenticating the user. If you are signing into a terminal session or through SSH and authenticate, your shell session will be set as a "login" shell.
If you start a new shell session from within your authenticated session, like we did by calling the bash command from the terminal, a non-login shell session is started. You were were not asked for your authentication details when you started your child shell.
Another distinction that can be made is whether a shell session is interactive, or non-interactive.
An interactive shell session is a shell session that is attached to a terminal. A non-interactive shell session is one is not attached to a terminal session.
Check this link for details - Digital Ocean Tutorials

Install and Deploy Django app on Heroku

I often forget steps and wish there was a quick instructional guide on deploying a django project on Heroku.
How to Install and Deploy a Django app on Heroku?
I have posted a step-by-steps answer for steps that have worked for me.
You will get:
Django app both on heroku and your computer.
Postgres databases on both machines
git/bitbucket
authentication: login, logout, register, forgot pass, email authentication only (optional & default)
static files working on both machines
Bootstrap 3.0.3 included
South Migrations (instructions)
Requirements
heroku account
github/bitbucket account
mac with OSX (tested on 10.9)
UPDATE:
To do an installation the quick way, check out the other answer.
Folder structure
PROJECT_WRAPPER - it will hold everything, including PS
DJANGO_PROJECT - it will hold the code
DJANGO_APP - the main app will have that name
Anywhere you see those, replace with your real names!!!
Virtual Env
If you don’t have virtualenv, you need to get it. It will allow you to have separate installations of software for each project:
pip install virtualenv
then we create our project:
cd ~
mkdir PROJECT_WRAPPER && cd PROJECT_WRAPPER
virtualenv venv
now you have a dedicated folder that will contain independent installations and version of python, django, etc.
We activate and and start working on project the following way:
source venv/bin/activate
Postrges app
Just before we continue, we will install postgres.app. Grab it from:
http://postgresapp.com/
Install.
We will now hook up our environment with it:
PATH=/Applications/Postgres.app/Contents/MacOS/bin/:$PATH
Requirements.txt
Now we will need to install the following things:
Python, Django - no explanations required
South - Migrations of database (dev version of Django does not require it)
django-toolbelt - required by heroku and includes everything required for heroku
psycopg - postgres database
simplejson, mixpanel - these are optional, you could skip if you didn't like
So to create the requirements.txt file, we will get it ready from my git repository:
clone https://raw2.github.com/mgpepe/django-heroku-15/master/requirements.txt -o requirements.txt
Now with one command we will install everything from our requirements.txt:
pip install -r requirements.txt
Great, now we can verify that we have django with:
python -c "import django; print(django.get_version())"
Start a Django Project
Let’s start the project with this line and don’t forget the dot in the end:
django-admin.py startproject DJANGO_PROJECT .
Now if you type ls you should see a folder with your project name that contains your Django project.
To see if it all works run:
python manage.py runserver
DATABASE
Run the Postgres app.
Create a database with (I used my osx username):
createdb YOUR_DATABASE_NAME --owner=YOUR_OSX_USERNAME
change the DATABASES to look like this:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'YOUR_DATABASE_NAME',
'USER': 'YOUR_OSX_USERNAME',
'PASSWORD': 'YOUR_DATABASE_PASSWORD', #might be empty string ''
'HOST': '127.0.0.1',
# 'PORT': '5432',
}
}
And also let’s hook up the South migrations. Your INSTALLED_APPS should look like that:
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'south',
)
Change the SECRET_KEY variable to something else than what it is.
Now if everything was fine you should be able to create the first tables with:
python manage.py syncdb
FIRST APP
Now make your first app in your project
python manage.py startapp DJANGO_APP
in the file: ~/PROJECT_WRAPPER/DJANGO_PROJECT/settings.py
add the DJANGO_APP app to the list in the variable INSTALLED_APPS. Should look like that:
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'south',
'DJANGO_APP',
)
TEMPLATES
in settings file add the line:
TEMPLATE_DIRS = [os.path.join(BASE_DIR, 'templates')]
In order for the templates to be well organized and working, we will copy base.html in one folder and the rest of templates in the app itself:
cd ~/PROJECT_WRAPPER/
mkdir templates
curl https://raw2.github.com/mgpepe/django-heroku-15/master/templates/base.html -o base.html
Now the rest of templates:
cd ~/PROJECT_WRAPPER/DJANGO_APP/
mkdir templates && cd templates
mkdir DJANGO_APP
curl https://raw2.github.com/mgpepe/django-heroku-15/master/DjMainApp/templates/DjMainApp/changepass.html -o changepass.html
curl https://raw2.github.com/mgpepe/django-heroku-15/master/DjMainApp/templates/DjMainApp/forgot_pass.html -o forgot_pass.html
curl https://raw2.github.com/mgpepe/django-heroku-15/master/DjMainApp/templates/DjMainApp/home.html -o home.html
curl https://raw2.github.com/mgpepe/django-heroku-15/master/DjMainApp/templates/DjMainApp/login.html -o login.html
curl https://raw2.github.com/mgpepe/django-heroku-15/master/DjMainApp/templates/DjMainApp/logout.html -o logout.html
curl https://raw2.github.com/mgpepe/django-heroku-15/master/DjMainApp/templates/DjMainApp/registration.html -o registration.html
curl https://raw2.github.com/mgpepe/django-heroku-15/master/DjMainApp/templates/DjMainApp/splash.html -o splash.html
AUTH SYSTEM WITH EMAIL
Since it has been lately fashionable to use email instead of username, we will do that too.
*NOTE: if you decide not to use it, you can skip this step BUT you have to edit the views and templates to use username instead of email. *
In settings add the following line:
AUTHENTICATION_BACKENDS = (DJANGO_PROJECT.backends.EmailAuthBackend’,)
then copy the file backends.py in our project directory:
cd ~/PROJECT_WRAPPER/DJANGO_PROJECT/
clone https://raw2.github.com/mgpepe/django-heroku-15/master/DjangoHerokuIn15/backends.py -o backends.py
HEROKU LOCALLY
You can simulate heroku working on your computer with Foreman. Let’s create the simplest configuration file:
cd ~/PROJECT_WRAPPER
echo "web: gunicorn DJANGO_PROJECT.wsgi" > Procfile
foreman start
Now that you see it working without errors stop it with CTRL+C
in settings all the way at the bottom add:
# HEROKU
###########################
# Parse database configuration from $DATABASE_URL
if os.environ.has_key('DATABASE_URL'):
import dj_database_url
DATABASES['default'] = dj_database_url.config()
# Honor the 'X-Forwarded-Proto' header for request.is_secure()
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
# Allow all host headers
ALLOWED_HOSTS = ['*']
In your DJANGO_PROJECT/wsgi.py file and add the following to bottom:
from dj_static import Cling
application = Cling(get_wsgi_application())
STATIC FILES
Ideally you would server static files from Amazon or something like that. But for simple sites you could use Django. Setting it up requires you to append this in settings file:
# HEROKU STATIC ASSETS CONFIGURATION
################################
import os
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
STATIC_ROOT = 'staticfiles'
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
and put all static files in a specific folder. First go to your project folder with something like:
cd ~/PROJECT_WRAPPER/DJANGO_PROJECT/
and now you can just copy/paste the rest:
mkdir static && cd static
mkdir css && cd css
clone https://raw2.github.com/mgpepe/django-heroku-15/master/DjangoHerokuIn15/static/css/bootstrap.min.css -o bootstrap.min.css
clone https://raw2.github.com/mgpepe/django-heroku-15/master/DjangoHerokuIn15/static/css/styles.css -o styles.css
cd ..
mkdir js && cd js
clone https://raw2.github.com/mgpepe/django-heroku-15/master/DjangoHerokuIn15/static/js/bootstrap.min.js -o bootstrap.min.js
cd ..
mkdir img && cd img
In this last folder, you will put all images you need.
URL SETTINGS AND VIEWS
In urls.py copy these lines right before ‘example’:
url(r'^$', "pmfmain.views.splash", name="splash"),
url(r'^login$', "pmfmain.views.login_view", name="login"),
url(r'^signup$', "pmfmain.views.register", name="signup"),
url(r'^forgot$', "pmfmain.views.forgot_pass", name="forgotmypass"),
url(r'^logout$', "pmfmain.views.logout_user", name="logout"),
url(r'^dashboard$', "pmfmain.views.home", name="home”),
then copy views.py from my github repo to your DJANGO_PROJECT folder:
cd ~/PROJECT_WRAPPER/DJANGO_APP/
rm views.py
clone https://raw2.github.com/mgpepe/django-heroku-15/master/DjMainApp/views.py -o views.py
Do a find & replace replacing DjMainApp with your real DJANGO_APP name throughout the whole views.py
clone https://raw2.github.com/mgpepe/django-heroku-15/master/DjMainApp/forms.py -o forms.py
GIT
Some files need not be in git, so let’s set the config for this:
echo -e "venv\n*.pyc\n*.log\n*.pot\nstaticfiles" > .gitignore
and now lets commit:
git init
git add .
git commit -m ‘initial commit of django app’
Create a repository in git, then copy the git url (the one that ends in .git). Then:
git remote add origin THE_URL
git pull origin master
BITBUCKET ALTERNATIVE
If you don’t want to pay for github and you want your repository private, you can use bitbucket.
Login to your account
Create a new repository
Click add existing project
git remote add origin https://USERNAME#bitbucket.org/USERNAME/REPOSITORY_NAME.git
MULTIPLE HEROKU ACCOUNTS & KEYS
Even if you never have to have multiple heroku accounts, it is an easy way to setup and use it even for one account. So on we go:
cd ~
heroku plugins:install git://github.com/ddollar/heroku-accounts.git
the add a heroku account with:
heroku accounts:add personal
Enter your Heroku credentials.
Email:YOUR_HEROKU_EMAIL
Password: YOUR_HEROKU_PASSWORD
It says it in the console, and you have to do it:
Add the following to your ~/.ssh/config
Host heroku.personal
HostName heroku.com
IdentityFile /PATH/TO/PRIVATE/KEY
IdentitiesOnly yes
Go to your project folder with something like:
cd ~/PROJECT_WRAPPER
and then set the new account as:
heroku accounts:set personal
To create a new ssh KEY:
ssh-keygen -t rsa
When asked for name, write the full path and name as shown. then type your password or leave blank
Then add the keys both to your OSX and heroku:
heroku keys:add ~/.ssh/YOUR_KEY_NAME.pub
ssh-add ~/.ssh/YOUR_KEY_NAME
DEPLOYING HEROKU FILES
Now that you have keys in order, you should be able to do
heroku apps
and see that there are no apps. To add your first app:
heroku apps:create YOUR_APP_NAME
And now to upload to the server:
git push heroku master
now go to YOUR_APP_NAME.herokuapp.com to see your site!
DOMAIN SETUP
remains to be explained if anybody wants, let me know
NOTES
In-depth documentation at:
https://docs.djangoproject.com/en/1.6/intro/tutorial01/
https://devcenter.heroku.com/articles/getting-started-with-django
In my other answer, the process is well described, but takes time. So I have made a ready installation that is good to go in less than 15minutes.
https://github.com/mgpepe/django-heroku-15
If you'd prefer the full explanation with the long path see the answer below.
THESE ARE THE ERRORS WHICH I FIND WHILE WORKING ON DJANGO FOR 2 YEARS [ENJOY]
Dyno should be added/seen in heroku->resources and if it is not added in resources of Heroku then it means there is a problem in the
"Procfile"
web: gunicorn [django_project].wsgi --log-file -
"django_project" above is your project name , change it to your project name
Remember to do changes in the settings.py file
DEBUG=True
ALLOWED_HOSTS = ["your-app.herokuapp.com","127.0.0.1"]
add this in settings.py file
#->this should be in the middleware
'whitenoise.middleware.WhiteNoiseMiddleware',
#->this at the bottom
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
[ First do "pip install django-heroku" ]
place this at the top of settings.py file:
import django_heroku
place this at the bottom of "settings.py" file:
django_heroku.settings(locals())
Heroku only works with postgres, remember this
[ go to https://www.elephantsql.com/ ]
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": "",
"USER": "",
"PASSWORD": "",
"HOST": "",
"PORT": "5432",
}
}
Make Sure database in the background, if not running, start "postgres" in the services.msc.
[ This is in taskmanager->Services->postgresql->right click->start]
python manage.py migrate
go to "your app" in heroku and go to "settings" and select "Add buildpack" in the settings and select "python"
####################### Important ##############################
==> Create a new Git repository Initialize a git repository in a new or
existing directory
cd my-project/
git init
heroku git:remote -a iris-django-ml
==> Deploy your application
Commit your code to the repository and deploy it to Heroku using Git.
git add .
git commit -am "make it better"
git push heroku master
"run this command in your directory"
heroku login
python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser
restart again with deleting your git file of your working directory, delete heroku project (settings -> bottom)