Penso che il modo migliore per affrontare entrambi i vostri comportamenti desiderati non è con i segnali, ma piuttosto con un override save() e delete() metodo sul tavolo through
quale si desidera definire in modo esplicito utilizzando l'argomento through
vedi: https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.ManyToManyField.through. e questo: https://docs.djangoproject.com/en/dev/topics/db/models/#overriding-predefined-model-methods
Qualcosa di simile a questo:
# -*- coding: utf-8 -*-
from django.db import models
class Item(models.Model):
# fields
# ...
class Collection(models.Model):
items = models.ManyToManyField(Item, related_name="collections", through="CollectionItem")
# other fields
# ...
class CollectionItem(models.Model):
collection = models.ForeignKey(Collection)
item = models.ForeignKey(Item)
def save(self, *args, **kwargs):
# Only allow this relationship to be created on some_condition
# Part 1 of your question.
if some_condition:
super(CollectionItem, self).save(*args, **kwargs)
# Update some fields on Collection when this
# relationship is created
# Part 2 of your question (1/2)
self.Collection.updateSomeFields()
def delete(self, *args, **kwargs):
collection = self.collection
super(CollectionItem, self).delete(*args, **kwargs)
# Update some fields on Collection when this relationship
# is destroyed.
# Part 2 of your question (2/2)
collection.updateSomeFields()
Per inciso, vi accorgerete che l'aggiunta di un rapporto sarà causare un segnale risparmiare sulle questo attraverso il modello.
E, per quanto riguarda i segnali, una volta che il tavolo passante è in posizione, si sarà in grado di ascoltare i segnali pre_save e/o post_save, ma nessuno di questi vi consentirà di porre direttamente il veto alla creazione della relazione.
Se uno o entrambi i modelli sono forniti da un terzo partito e davvero non si può creare la tabella attraverso, allora sì, il percorso del segnale può essere l'unico modo per andare.
https://docs.djangoproject.com/en/dev/ref/signals/#m2m-changed
In questo caso, si poteva ascoltare per l'evento m2m_changed e innescare aggiornamenti tuoi oggetti da collezione (parte 2 della tua domanda) e retroattivamente eliminare relazioni impropriamente creati (parte 1 della tua domanda). Tuttavia, poiché quest'ultimo è un po 'fugly kludgy, mi piacerebbe restare con l'esplicita attraverso tavolo se potete.
Per il rilascio 1, probabilmente si dovrebbe utilizzare ciclo di pulizia del form per convalidare i dati (che facilita la messaggistica di validazione), che viene poi inviano al [save_m2m] (https: //docs.djangoproject.it/it/dev/topics/forms/modelforms/# the-save-method) –
@Hedde: preferirei una soluzione vicina ai modelli, perché i miei dati probabilmente non verranno modificati da un modulo. (Più probabile attraverso gli strumenti CLI e un'API esposta). – Constantinius
È possibile sovrascrivere i metodi di salvataggio del modello, almeno per parte della logica, ma se si sta implementando un'API sembra che tale logica appartenga al livello di autorizzazione dell'API. Tastypie è una grande API ricca che funziona bene con Django. –