since I couldn't find any topics about it, I would like to share my experience about getting django 1.9.7 to work in Pythonista 3.
- Install django by using a pip substitute like stash-pip or pipista, or just download a django archive and move the contained django directory to site-packages.
- If you don't have an existing django project but want to create a new one, open and run site-packages/django/bin/django-admin.py with "startproject foo" as argument, where foo is the name of your new project. This should create a new directory named foo with some default files in it, including a manage.py script for managing your project.
- Using manage.py is where I ran into trouble:
- It seems one cannot use stash to run manage.py, I got an error saying that if DEBUG was False, ALLOWED_HOSTS had to be filled - but DEBUG was set to True in my settings file. You must open and run manage.py directly.
- By default, when starting the development server, django uses two processes to auto-reload when changes are made to the project files. As fork() is not supported in Pythonista, you must run manage.py with arguments "runserver --noreload".
- Whenever manage.py is executed, Django initializes all apps and models, which must only happen once. Since the Pythonista interpreter is not reset between script executions, I got various errors and warnings with django complaining about "populate is not reentrant", "reloading models is not advised" and other strange effects. What finally worked for me was calling a reset script at the top of manage.py:
exec(compile(open("../reset.py").read(), "../reset.py", 'exec'))
with reset.py being:
import sys bases = set(['posix', 'encodings.utf_8', 'token', '__main__', 'os', 'heapq', 'importlib._bootstrap_external', 'zipimport', '_heapq', '_functools', 'encodings', 'json.scanner', '_outputcapture', 'marshal', 'collections.abc', 'importlib._bootstrap', '_weakrefset', '_signal', '_bootlocale', 'codecs', 'io', 'tokenize', 'importlib', 'json.decoder', 'copyreg', 'abc', 'posixpath', '_debugger_ui', 'encodings.latin_1', '_warnings', '_operator', 'sysconfig', 'encodings.ascii', 'itertools', 'json', '_collections', 'operator', 'importlib.util', 'os.path', 'sys', 'types', 'sre_parse', 'sre_compile', '_io', 'appex', '_sitebuiltins', 'importcompletion', 'imp', 'stat', 'warnings', '_thread', '_frozen_importlib', 'functools', 'json.encoder', 'contextlib', 'importlib.abc', 'site', 'keyword', '_codecs', 'sre_constants', '_collections_abc', 'weakref', '_imp', '__future__', '_stat', '_sre', 'encodings.aliases', 'errno', 'collections', '_weakref', '_frozen_importlib_external', '_json', '_sysconfigdata', 'importlib.machinery', 'genericpath', 'builtins', 're', '_locale', '_appex', 'reprlib']) names = list(sys.modules.keys()) for name in names: if name not in bases: del sys.modules[name]
I know that this is a hackish workaround that may not even work in all cases, but so far it did the job for me. Syncing an sqlite3 database, running the development server and using django's admin interface (with grappelli plugin) worked flawlessly.
The only thing that I think might be improved is that Pythonista's built-in webbrowser does neither have an address bar nor a reload button, and I don't like to use an external browser since ios then stops the webserver after a while. Also, Pythonista always switches from the browser to the console when output occurs, which is problematic since django's dev server logs every request by default. But maybe it can somehow be configured to run quietly.
Finally, I want to thank Ole for having created such a powerful and versatile tool!