étrangère J'ai un modèle avec un entier unique qui doit augmenter en ce qui concerne une clé étrangère, et le code suivant est la façon dont je gère actuellement il:Django - AutoField en ce qui concerne une clé
class MyModel(models.Model):
business = models.ForeignKey(Business)
number = models.PositiveIntegerField()
spam = models.CharField(max_length=255)
class Meta:
unique_together = (('number', 'business'),)
def save(self, *args, **kwargs):
if self.pk is None: # New instance's only
try:
highest_number = MyModel.objects.filter(business=self.business).order_by('-number').all()[0].number
self.number = highest_number + 1
except ObjectDoesNotExist: # First MyModel instance
self.number = 1
super(MyModel, self).save(*args, **kwargs)
I ont les questions suivantes à ce sujet:
- Plusieurs personnes peuvent créer
MyModel
instances pour le mêmebusiness
, partout sur l'internet. Est-il possible pour 2 personnes créantMyModel
instances en même temps, et.count()
renvoie 500 en même temps pour les deux, et puis tous les deux essaient de définir essentiellementself.number = 501
en même temps (lever une IntegrityError)? La réponse semble évidente: "oui, ça pourrait arriver", mais j'ai dû demander. - Existe-t-il un raccourci, ou "Meilleure façon" de le faire, que je peux utiliser (ou peut-être un
SuperAutoField
qui gère cela)?
Je ne peux pas frapper un while model_not_saved:
try:
, except IntegrityError:
en, parce que d'autres dispositifs de retenue dans le modèle pourrait conduire à une boucle sans fin, et une catastrophe pire que Tchernobyl (peut-être pas tout à fait si mal).
@Paul - merci. Je ne comprends pas. Je ne savais pas qu'une transaction garantirait qu'aucune modification ne soit apportée aux lignes lues pendant la transaction, ainsi que, bien sûr, protégeant la phase de validation en cas d'échec partiel. C'est tellement? Si oui, je peux simplement envelopper enregistrer dans '@ commit_on_success', non? – orokusaki
@Paul - Il semble également que les transactions ne résolvent pas le problème de 'IntegrityError' d'une autre contrainte brisée pouvant être confondue avec celle causée par' number' pendant la simultanéité. – orokusaki
Le comportement précis des transactions dépend de la base de données que vous utilisez et de la manière dont vous l'avez configurée.Si vous activez le middleware de transaction et que vous définissez le niveau d'isolation sur readable dans votre base de données, votre méthode fonctionnera telle quelle. Cela ne sera probablement pas un problème de performance dans ce cas, mais cela pourrait avoir un impact sur le reste de votre code. –