Django: Avoid clash of port 8000 (runserver) - django

I develop on serveral projects at once.
If I run the runserver twice, I get this error:
System check identified no issues (0 silenced).
September 10, 2021 - 10:44:26
Django version 3.1.4, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
Error: That port is already in use.
I know that I can supply a different port manually, but a more automatic approach would be nice.
How could I solve this clash without manually giving each project a port by hand?
I have more than 50 systems on my laptop, and I don't want to give them each a port number by hand.

You can implement something like following.
Add RUN_SERVER_PORT in settings.py
RUN_SERVER_PORT = 8080
Implement following code in manage.py
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
from django.core.management.commands.runserver import Command as runserver
from django.conf import settings
def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'accountant.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
runserver.default_port = settings.RUN_SERVER_PORT
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()
Proof of Work:
python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
September 19, 2021 - 12:47:59
Django version 3.2.6, using settings 'accountant.settings'
Starting development server at http://127.0.0.1:8080/
Quit the server with CONTROL-C.
You can use any available port in RUN_SERVER_PORT

You can create your own manage command runsever_foo.
Then you can fetch the default value for the port from settings.py or from os.environ.

Reference to this post: https://stackoverflow.com/a/38319452/16936785
I would recommend to amend the server port under manage.py into the following for a random port selection:
import random
from django.core.management.commands.runserver import Command
port_number = random.randint(8000, 8888)
Command.default_port = str(port_number)

put this in your .bashrc .zshrc or .bash_profile depends on your environment.
#!/usr/bin/env bash
function runserver()
{
local PORTNUM=8000
for (( ; ; )); do
nc -z 127.0.0.1 $PORTNUM
[ $? -ne 0 ] && break
PORTNUM=$(( $RANDOM % 1000 + 8000 ))
done
python manage.py runserver $PORTNUM $#
}
Then just run runserver and it should bring up a test server with a port in the range of [8000, 9000)
This function uses netcat to test if the port is available, you might need to install netcat.

To run Django on different port
python manage.py runserver <your IP>:<port> :
python manage.py runserver 0.0.0.0:5000
Or
python manage.py runserver <port> : python manage.py runserver 5000
For automation
Create a bash script like django_5000 and django_7000 where you execute differents command according to your desired port.

Related

Gunicorn binding specifically to multi-endpoint websites running on different ports

I am using Gunicorn + NGINX to deploy a multi-endpoint Django REST application. The application runs with
pipenv shell
foreman start
which runs 5 different websites on different ports on localhost. I am trying to deploy just a single one of these websites that runs on port 8000 using Gunicorn. However, I am facing some issues while binding shown down below. I am quite sure how to exactly bind this application using the following line:
gunicorn --bind 0.0.0.0:8000 myproject.wsgi
Here is the WSGI file that I am using:
import os
from django.core.wsgi import get_wsgi_application
if not "DJANGO_SETTINGS_MODULE" in os.environ:
raise Exception("DJANGO_SETTINGS_MODULE not set")
os.environ.setdefault("PERFORM_TIME_CONSUMING_INITIALIZATIONS", "True")
application = get_wsgi_application()
And this is how the websites were exported:
export default {
website1: "http://localhost:8007",
website2: "http://localhost:8000",
website3: "http://localhost:8005",
website4: "http://localhost:8010",
website5: "http://localhost:8009",
};

Django runserver on Chromebook (Crostini)

I'm using a Chromebook HP 11 G5 EE and try to develop with Django.
I use Crostini (Linux terminal into Chrome OS with no developper mode).
I've created a virtualenv inside my home directory and installed with pip all my requirements.
When I try to do (with source bin/activate) :
./manage.py runserver
It returns me :
Performing system checks...
System check identified no issues (0 silenced).
May 28, 2019 - 20:02:11
Django version 2.1.5, using settings 'myproject.settings'
Starting development server at http://0.0.0.0:8000/
Quit the server with CONTROL-C.
Error: You don't have permission to access that port.
I'd try to set parameters like 0.0.0.0:8000, penguin.linux.test:8000, to change ports, I've got the same error.
Is someone had the same issue and fixed it ?
Thanks !
How about this:
./manage.py runserver 0.0.0.0:8000

Django - How to check if server is running in ASGI or in WSGI mode?

We are running the same django project in WSGI mode for handling HTTP requests and in ASGI mode for handling WebSockets. For WSGI mode we are using gunicorn3 server:
gunicorn3 --pythonpath . -b 0.0.0.0:8000 chat_bot.wsgi:application
For ASGI mode we are using daphne server:
daphne --root-path . -b 0.0.0.0 -p 8001 chat_bot.asgi:application
How to programatically detect which mode currently is running GreenUnicorn+WSGI or Daphne+ASGI?
One possibility:
Inside of your wsgi.py file you can set an environment variable to one value you won't be setting anywhere else:
os.environ.setdefault('SERVER_GATEWAY_INTERFACE', 'Web')
And then inside of asgi.py set it to a different variable:
os.environ.setdefault('SERVER_GATEWAY_INTERFACE', 'Asynchronous')
Then in other parts of your code, just check against the environment variable:
if os.environ.get('SERVER_GATEWAY_INTERFACE') == 'Web':
# WSGI, do something
else:
# ASGI, do something else

Eventlet is_monkey_patched issues False

Hello I have a django app. My whole system configuration is the following: python 3, django 1.11, eventlet 0.21.0.
1) Nginx as an upstream server:
upstream proj_server {
server unix:///tmp/proj1.sock fail_timeout=0;
server unix:///tmp/proj2.sock fail_timeout=0;
}
2) Supervisor that controls workers. There is a gunicorn worker:
[program:proj]
command=/home/vagrant/.virtualenvs/proj/bin/gunicorn -c /vagrant/proj/proj/proj/deploy/gunicorn.small.conf.py proj.wsgi:application
directory=/vagrant/proj/proj/proj/deploy
user=www-data
autostart=true
autorestart=true
stdout_logfile=/var/log/supervisor/proj.log
3) This is a gunicorn.small.conf content:
bind = ["unix:///tmp/proj1.sock", "unix:///tmp/proj2.sock"]
pythonpath = "/vagrant/proj/proj/proj/deploy"
workers = 2
worker_class = "eventlet"
worker_connections = 10
timeout = 60
graceful_timeout = 60
4) And this is proj.wsgi content:
"""
WSGI config for proj project.
This module contains the WSGI application used by Django's development server
and any production WSGI deployments. It should expose a module-level variable
named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover
this application via the ``WSGI_APPLICATION`` setting.
Usually you will have the standard Django WSGI application here, but it also
might make sense to replace the whole Django WSGI application with a custom one
that later delegates to the Django one. For example, you could introduce WSGI
middleware here, or combine a Django application with an application of another
framework.
"""
import eventlet
eventlet.monkey_patch()
from eventlet import wsgi
import django.core.handlers.wsgi
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "proj.settings")
# This application object is used by any WSGI server configured to use this
# file. This includes Django's development server, if the WSGI_APPLICATION
# setting points here.
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
# Apply WSGI middleware here.
# from helloworld.wsgi import HelloWorldApplication
# application = HelloWorldApplication(application)
So, as you can see there is a chain: nginx as an upstream server calls one of the gunicorn eventlet workers using two sockets proj1.sock or proj2.sock.
Note that according with the eventlet documentation I try to use eventlet.monkey_patch() as early as possible. The most appropriate place for that is proj.wsgi that is called by gunicorn in the first place.
However it seems that library isn't monkey patched.
To check this I added to the proj/proj/proj/__init__.py (the first module that called by the django application) the following code:
import eventlet
import os
print("monkey patched os is: " + str(eventlet.patcher.is_monkey_patched('os')))
print("monkey patched select is: " + str(eventlet.patcher.is_monkey_patched('select')))
print("monkey patched socket is: " + str(eventlet.patcher.is_monkey_patched('socket')))
print("monkey patched time is: " + str(eventlet.patcher.is_monkey_patched('time')))
print("monkey patched subprocess is: " + str(eventlet.patcher.is_monkey_patched('subprocess')))
then i issued **./manage.py check** and got that answer:
monkey patched os is: false
monkey patched select is: false
monkey patched socket is: false
monkey patched time is: false
monkey patched subprocess is: false
What am I doing wrong?
What if you change proj.wsgi file content to one line raise Exception? That should eliminate eventlet from suspects.
I'm not good with Django, here's a pure speculation:
based on name, proj.wsgi is executed when WSGI server is about to start
manage.py check doesn't seem to be related to remote network service (WSGI), seems to be a general management command, so it shouldn't execute WSGI related code
One possible solution, taken from your question text:
proj/proj/proj/init.py (the first module that called by the django application
Try to put monkey_patch call in there.
P.S.: you don't need supervisor for gunicorn, its master process (arbiter) is designed to run forever in spite of problems with workers.

How to restart a Django development web server in virtual machine on file modification?

I have a VirtualBox machine managed by Vagrant. On this machine I run a Django development web server:
./manage.py runserver 0.0.0.0:8080
The codebase is big so for faster code reload I installed pyinotify. Django supports it since 1.7. I'm using 1.7.
The codebase sits in a synced folder (NFS) and I'm using Sublime 3 to edit files on my host machine (OS X).
However inotify doesn't go well with NFS and the code autoreload do not work.
How do I restart a dev server in the VM?
I have a rudimentary web server running next to a dev server. This simple web server listens for a request (on a different port) and touches the project's manage.py. This in turn triggers a restart:
reloader.py
#!/usr/bin/env python
import os
import logging
import SocketServer
from BaseHTTPServer import BaseHTTPRequestHandler
logging.basicConfig(level=logging.INFO,
format='%(asctime)s %(message)s',
datefmt='%m/%d/%Y %I:%M:%S %p')
PORT = 9001
FILE_TO_TOUCH = '/path/to/myenv/manage.py'
def touch(fname, times=None):
with open(fname, 'a'):
os.utime(fname, times)
class HandleTouch(BaseHTTPRequestHandler):
def do_GET(self):
logging.info("Touching %s", FILE_TO_TOUCH)
touch(FILE_TO_TOUCH)
self.send_response(200)
self.send_header("Content-Length", '0')
self.end_headers()
httpd = SocketServer.TCPServer(("", PORT), HandleTouch)
logging.info("Server listening on port %s", PORT)
httpd.serve_forever()
On the host machine I use a simple shell command to watch for file changes and hit the reloader's endpoint:
watcher.sh
#!/bin/sh
watchmedo shell-command -c 'curl http://192.168.10.10:9001' -R -i '/path/to/myenv/manage.py' -p '*.py' ./
Where watchmedo is a utility from watchdog.