ho tale modello:Django: fusione oggetti
class Place(models.Model):
name = models.CharField(max_length=80, db_index=True)
city = models.ForeignKey(City)
address = models.CharField(max_length=255, db_index=True)
# and so on
Dato che io li sto importazione da molte fonti, e gli utenti del mio sito sono in grado di aggiungere nuovi luoghi, ho bisogno di un modo per unirle da un interfaccia di amministrazione. Il problema è che il nome non è molto affidabile in quanto possono essere scritte in molti modi diversi, ecc io sono abituato a usare qualcosa di simile:
class Place(models.Model):
name = models.CharField(max_length=80, db_index=True) # canonical
city = models.ForeignKey(City)
address = models.CharField(max_length=255, db_index=True)
# and so on
class PlaceName(models.Model):
name = models.CharField(max_length=80, db_index=True)
place = models.ForeignKey(Place)
query come questa
Place.objects.get(placename__name='St Paul\'s Cathedral', city=london)
e unire come questo
class PlaceAdmin(admin.ModelAdmin):
actions = ('merge',)
def merge(self, request, queryset):
main = queryset[0]
tail = queryset[1:]
PlaceName.objects.filter(place__in=tail).update(place=main)
SomeModel1.objects.filter(place__in=tail).update(place=main)
SomeModel2.objects.filter(place__in=tail).update(place=main)
# ... etc ...
for t in tail:
t.delete()
self.message_user(request, "%s is merged with other places, now you can give it a canonical name." % main)
merge.short_description = "Merge places"
come si può vedere, devo aggiornare tutti gli altri modelli con FK per posizionare con nuovi valori. Ma non è una soluzione molto buona dato che devo aggiungere ogni nuovo modello a questa lista.
Come faccio a "sovrapporre in cascata" tutte le chiavi esterne ad alcuni oggetti prima di eliminarli?
O forse ci sono altre soluzioni per fare/evitare la fusione
FWIW Ho trovato questo esempio più completo: http://djangosnippets.org/snippets/2283/ – dpn
Snippet non sembra funzionare per me più, non riesce in ForeignKey. La transazione Plus è ammortizzata in favore di atomico. Inoltre iteritems() diventa items() in python3. (gli ultimi due numeri erano facili da risolvere, il primo no). – gabn88
Nel risolvere il primo numero ho scoperto che il problema è probabile con il groupobjectpermissions di django guardian. Non è stato possibile risolverlo però :( – gabn88