0

I'm currently using django's clean() method to implement custom validations in a Model.

A have a DB for example that is 1:m and have the following structure:

| Id         | Foreign Key | Date         |
|:-----------|------------:|:------------:|
| 1          |      1      | 20-11-2019   |
| 2          |      1      |    None      |

The custom validation grants that for the same Foreign Key, there is only one row where date = None

As save() is not called in this method, @transaction.atomic would not work, hence, what is the best way to grant atomicity with this method?

I'm using python 3.7, django 2.2.6 and Postgresql

  • I don't get your question. If you are using the `clean()` method and something is not right you should raise `ValidationError` right? The raised `ValidationError` would roll back any transaction from parent calls. It'd help if you showed some code I think – heyhugo Dec 09 '19 at 22:04
  • Not exactly, imagine for example that two rows are being inserted in the same time and they are equal. If one runs clean() method while the other run it with a very little difference of time, it could happen that both will return true because it is not accounting for the one that will be inserted first. In the end, I could end with two equal rows with say, two nulls on date. – Victor Esteves Dec 10 '19 at 01:06

2 Answers2

0

You could set ATOMIC_REQUESTS on your settings to make all requests atomic

Iain Shelvington
  • 31,030
  • 3
  • 31
  • 50
  • I think that doesn't apply in this situation, as I'm performing some custom validations in the backend before the model is saved. – Victor Esteves Dec 09 '19 at 20:17
0

Ok I'm not a 100% I get you problem but from your comment, you seem to describe a race condition.

You could create UNIQUE indexes similar to what is described here: https://stackoverflow.com/a/8289253/929109

Having those indexes would cause an IntegrityError being raised if you try to insert a 2nd record will NULL for the field. You could catch this exception and do whatever then.

heyhugo
  • 1,015
  • 9
  • 14