I have some signal handlers that work on the Django user. Additionally I'm using South. These signal handlers depends on some migrations th开发者_如何学Pythonat must run in before.
When Django executed snycdb and creates the admin user these migrations haven't run and the signal handlers raise an exception.
I'm searching for a way to detect if Django currently runs syncdb so that the signal handerls can skip execution.
I trap the DatabaseError exception and check if the ContentType entry for the model I'm trying to use exists, if it doesn't I assume syncdb is happening, otherwise rollback the transaction and re-raise the original exception. This method incurs in an extra DB access only when DatabaseError is raised.
with transaction.commit_on_success():
try:
content_type = ContentType.objects.get_for_model(kwargs['instance'])
for relation in WorkflowTypeRelation.objects.filter(content_type=content_type):
workflow_instance = WorkflowInstance.objects.create(content_object=kwargs['instance'],
workflow_type=relation.workflow_type)
except DatabaseError as database_error:
try:
ContentType.objects.get(model='workflowtyperelation')
except ContentType.DoesNotExist:
# Most probable running during syncdb phase,
# so ignore the exception
pass
except DatabaseError:
# ContentType model DB table doesn't exists,
# raise original exception
raise database_error
else:
# The ContentType model exists,
# there is something wrong with the DB
# raise original exception
transaction.rollback()
raise database_error
I don't think there is a way to know if syncdb is running, but there is a way to handle exceptions in python:
Just catch and exception and pass
:
try:
# code that deals with django user
except ExceptionYouAreGetting:
# seems like syncdb is running, let's pass for now
pass
AFAIK it's not possible to detect whether or not syncdb is running, however, when syncdb or loaddata is running, your signals will receive an extra argument raw.
@receiver(post_save, sender=ModelA)
def signal_handler(sender, **kwargs):
raw = kwargs.get('raw', False)
if not raw:
<do whatever>
This way, you can skip signals to be run when syncdb is being executed.
精彩评论