django model on_delete pass self to models.SET() -
for example, have book model, each book has author , tag.
def get_authors_first_tag(book): try: tag = book.author.tags.first() except: return none else: return tag.id class author(models.model): name = models.charfield(max_length=50) tags = models.manytomanyfield('tag') class book(models.model): name = models.charfield(max_length=50) author = models.foreignkey(author) tag = models.foreignkey('tag', null=true, on_delete=models.set(get_authors_first_tag))
i want, when deleting tag item, book's tag set author's first tag. how this? thanks. doc page - https://docs.djangoproject.com/en/1.9/ref/models/fields/#django.db.models.set
update. signals didn't help
from django.db.models.signals import post_delete django.dispatch import receiver class book(models.model): # temporaryly set null on delete, # becouse neds cannot use default behavior (models.cascade) tag = models.foreignkey('tag', null=true, on_delete=models.set_null) @receiver(post_delete, sender=tag) def delete_tag(instance, **kwargs): book in instance.book_set.all(): try: book.tag = book.author.tags.first() book.save() except: pass
update2 final working solution is: (dirty, works)
@receiver(post_delete, sender=tag) def delete_tag(instance, **kwargs): books = book.objects.all() book in books: # after tag item deleting, book.tag set none # if boook's tag null, it's author's first tag if not book.tag: book.tag = book.author.tags.first() book.save()
the set()
doesn't accept arguments, should use signal receiver:
from django.db.models.signals.pre_delete django.dispatch import receiver @receiver(pre_delete, sender=tag) def reset_tag(sender, **kwargs): tag = kwargs['instance'] book in books.filter(tag=tag): book.tag = book.author.tags.first() book.save()
put code models.py
or make sure file put receiver imported @ startup, receiver connected.
Comments
Post a Comment