How *not* to run Django code on syncdb
-
02-10-2019 - |
Question
I have some server startup code that is lying in the "models.py" of one of my Django apps. I need to run that code on server startup time.
The problem is, that code issues a SQL query, which prevents me from running syncdb
with psycopg2
(it breaks the transaction, and tables are not created.)
Putting the code in a middleware and raising django.core.exceptions.MiddlewareNotUsed
is not optimal as I'd like to have the effect in the Django shell too (and putting initialization code in a middleware doesn't sound right anyway.) Also I'd need to wait for the first request to do that. I want to run code on server startup, not when the first customer comes knocking on my website.
Server startup signals are still not implemented in Django, so that's not an option.
Thus, I'd like to somehow either:
- check if Django is running a syncdb, so I don't do the queries,
- or, alternatively, check it the corresponding tables are there, and if they are not, then, too, just don't do any queries
Non of the above two options have I found in any of the documentation. How do I do that? Or is there a better (i.e. sane) way of doing what I want to do?
Solution
Django should also load urls.py
on startup; I cannot tell you if that's a suitable place for your code, but give it a try if you want to!
OTHER TIPS
Have you considered connecting to the post_syncdb
signal? Perhaps you can run the custom SQL on receiving this signal. This may solve on part of your problem; you still have to figure out how to run the SQL on server startup.
You can put a check in settings.py:
import sys
...
IN_SYNCDB = ('syncdb' in sys.argv)
Then
if not settings.IN_SYNCDB:
# run SQL code
How about a bit of exception handling? When doing a query but the database table does not exist, a Django.db.utils.DatabaseError
is raised. Try..except the query code is the way of meeting your second criteria as I think.
Problem: models.py
class Foo(Model):
#model definition here
def fun():
obj=Foo.objects.get(pk=1)
#other logics here...
fun() #This causes a DatabaseError
Solution: models.py
class Foo(Model):
#model definition here
def fun():
obj=Foo.objects.get(pk=1)
#other logics here...
try:
fun()
except DatabaseError:
pass