Ho un utente condivide modello simile di seguito:Django unico personalizzato vincolo insieme
class Share(models.Model):
sharer = models.ForeignKey(User, verbose_name=_("Sharer"), related_name='sharer')
receiver = models.ForeignKey(User, verbose_name=_("Receiver"), related_name='receiver')
class Meta:
unique_together = (("sharer", "receiver"), ("receiver", "sharer"))
voglio salvare un singolo oggetto per sharer (S) e ricevitore (R) (ordine non fa questioni RS o SR). ma sopra unique_together non adempierà questo; Supponiamo che R-S sia nel database e quindi se salvi S-R non otterrò la convalida per questo. Per questo ho scritto convalida unica personalizzata per il modello Share.
def validate_unique(
self, *args, **kwargs):
super(Share, self).validate_unique(*args, **kwargs)
if self.__class__.objects.filter(Q(sharer=self.receiver, receiver=self.sharer)).exists():
raise ValidationError(
{
NON_FIELD_ERRORS:
('Share with same sharer and receiver already exists.',)
}
)
def save(self, *args, **kwargs):
# custom unique validate
self.validate_unique()
super(Share, self).save(*args, **kwargs)
Questo metodo funziona correttamente nell'uso normale.
Problema: Ho un algoritmo di matching che ottiene le richieste di un ricevitore una quota di e e salva Share oggetto (sia S-R o R-S) poi inviare loro risposta (oggetto di condivisione) quasi contemporaneamente. Siccome sto controllando la duplicazione con la query (nessun livello di database) ci vuole tempo, quindi alla fine ho 2 oggetti S-R e R-S.
Voglio una soluzione per questo che per un condivisore S e un ricevitore R Posso solo salvare un singolo oggetto di condivisione, S-R o R-S altrimenti ottenere qualche errore di convalida (come IntegrityError di databse).
Django = 1.4, Database = Postgresql
Grazie della risposta. Ho avuto 2 soluzioni. Uno per gestirlo con un numero di richiesta univoco (durante la corrispondenza nell'ID incrementato della cache Redis) e salvare il primo obj di condivisione della richiesta inferiore #, quindi attendere e ottenere share_obj per la richiesta più elevata #. ma l'ho risolto con la seconda soluzione (descritta da voi) per ordinare la lista di nomi utente di entrambi condivisori e ricevitori, in questo modo otterrò sempre lo stesso patter di condivisioni e ricevitori. Salverò la richiesta e se ottieni IntegrityError di postgresql, eseguo il rollback della transazione e Safley ottiene già l'oggetto S-R salvato. :) –