views:

76

answers:

1

Hello! I found an ambiguous place in one django-based application that I use in my project, please look at that:

if not request.method == 'POST' or not request.POST.get('openid'):
    raise RedirectException(next, _('Invalid POST data'))
if not UserAssociation.objects.filter(user=request.user).count() > 1 and not request.user.email:
    raise RedirectException(next, _("You must have at least one OpenID if you don't have email!"))
try:
    ua = UserAssociation.objects.get(openid_url=request.POST['openid'], user=request.user)
    ua.delete()
except UserAssociation.DoesNotExist:
    pass

Author is trying to achieve at least one record in table UserAssociation for users that don’t have email. But operations of checking records count and follow-up erasing are not atomic together. Consequently we can’t be sure that at the point of calling method delete() we still have more then 1 record for user at the table.

Is the any best practice of solving similar problems?

+1  A: 

In this case, it's easy: just use delete() on the filtered queryset rather than get()!

UserAssociation.objects.filter(openid_url=request.POST['openid'], user=request.user).delete()

In other cases, often it can help to wrap the SQL calls in a single database transaction. For instructions, read the the official transaction docs.

SmileyChris