Skip to content

Instantly share code, notes, and snippets.

@ocomsoft
Created August 31, 2017 23:16
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ocomsoft/ea581b172b72b23a1bcede21d9c76ee7 to your computer and use it in GitHub Desktop.
Save ocomsoft/ea581b172b72b23a1bcede21d9c76ee7 to your computer and use it in GitHub Desktop.
Run Django in pywebview and CherryPy
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Inspired by https://gist.github.com/nigma/4349257 and https://github.com/r0x0r/pywebview/blob/master/examples/flask_app/src/backend/main.py
import os
import webbrowser
from time import sleep
import django
from threading import Timer, Thread
import logging
import webview
os.environ["DJANGO_SETTINGS_MODULE"] = "config.settings.production"
import cherrypy
django.setup()
from django.conf import settings
from django.core.handlers.wsgi import WSGIHandler
logger = logging.getLogger(__name__)
class DjangoApplication(object):
HOST = "127.0.0.1"
PORT = 8001
def mount_static(self, url, root):
"""
:param url: Relative url
:param root: Path to static files root
"""
config = {
'tools.staticdir.on': True,
'tools.staticdir.dir': root,
'tools.expires.on': True,
'tools.expires.secs': 86400
}
cherrypy.tree.mount(None, url, {'/': config})
def open_browser(self):
# Wait for server to be UP!
while not self.url_ok(self.HOST, self.PORT):
sleep (0.1)
#Timer(3, webbrowser.open, ("http://%s:%s" % (self.HOST, self.PORT),)).start()
webview.create_window("Ocom App", "http://%s:%s" % (self.HOST, self.PORT), min_size=(800, 600))
def url_ok(self, url, port):
# Use httplib on Python 2
try:
from http.client import HTTPConnection
except ImportError:
from httplib import HTTPConnection
try:
conn = HTTPConnection(url, port)
conn.request("GET", "/dockerStatus/")
r = conn.getresponse()
return r.status == 200
except:
logger.exception("Server not started")
return False
def run(self):
cherrypy.config.update({
'server.socket_host': self.HOST,
'server.socket_port': self.PORT,
'engine.autoreload_on': False,
'log.screen': True
})
self.mount_static(settings.STATIC_URL, settings.STATIC_ROOT)
self.mount_static(settings.MEDIA_URL, settings.MEDIA_ROOT)
cherrypy.log("Loading and serving Django application")
cherrypy.tree.graft(WSGIHandler())
cherrypy.engine.start()
t = Thread(target=self.open_browser)
t.daemon = True
t.start()
cherrypy.engine.block()
if __name__ == "__main__":
DjangoApplication().run()
#Add to Requirements.txt
pywebview[qt5]==1.7 # On Linux..
CherryPy==11.0.0
@rocchidavide
Copy link

Great but why use CherryPy with Django? I miss the point

@ocomsoft
Copy link
Author

ocomsoft commented Nov 6, 2020

@rocchidavide I (stole) copied most of that code from here https://gist.github.com/nigma/4349257 not sure why they used that.
I can't remember now but I think based on line 78 it was the WSGI server.. HTH

@kachmul2004
Copy link

@ocomsoft Did you manage to get it work in recent versions of Django

@ocomsoft
Copy link
Author

@kachmul2004 Sorry I have not tried.

@mardukbp
Copy link

mardukbp commented Jun 1, 2023

The following works with Django 4.2. In DEBUG mode Django servers the static files. Otherwise one would need CherryPy.

#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import webview
from threading import Thread
from time import sleep
from http.client import HTTPConnection

host = "127.0.0.1"
port = 8000

def main():
    """Run administrative tasks."""
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'playground.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

    t = Thread(target=execute_from_command_line, args=(["manage.py", "runserver", "--noreload"],))
    t.daemon = True
    t.start()

    while not url_ok(host, port):
        sleep(0.1)

    webview.create_window("MyApp", f"http://{host}:{port}", min_size=(980, 1000))
    webview.start()

def url_ok(host: str, port: int):
    try:
        conn = HTTPConnection(host, port)
        conn.request("GET", "/")
        r = conn.getresponse()
        return r.status == 200
    except:
        # Server not started
        return False

if __name__ == '__main__':
    main()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment