Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Python: Веб-разработка и фреймворки > django, m2m в post_save


Автор: Hale 17.5.2012, 12:15
Всем привет.

django 1.4, python 2.7.2

Модель:

Код

from django.db import models, connection, transaction
from django.dispatch import receiver

class Tag(models.Model):
    name = models.CharField(max_length=100)


class Picture(models.Model):
    pict = models.ImageField(upload_to='somthing_dir')
    tag_m2m = models.ManyToManyField(Tag, null=True, blank=True)


@receiver(models.signals.post_save, sender=Picture, dispatch_uid='46jmehq9dfj18')
def post_save_picture(instance, created, **kwargs):
    if created:
        tagId = 2 # Для примера
        cursor = connection.cursor()
        cursor.execute('INSERT INTO gallery_picture_tag_m2m (picture_id, tag_id) VALUES (%s, %s)', [instance.id, tagId])
        transaction.commit_unless_managed()


После сохранения картинки нужно связать её с тегом.
Так как  в post_save неработает instance.tag_m2m.add(objTag) написал  инсерт.
Но по какойто причине он не отрабатывет. Причем не отрабатывает только с instance.id. Если вместо instance.id написать любое другое число, то все нормально.
Джанга где-то теряет этот инсерт, и не могу понять где. С комитами и флагами тоже игрался, результат тот же.

Подскажите, плиз, куда копать. 

Может как-то еще можно связать таблицы, помимо сырого инсерта.

Автор: Hale 19.5.2012, 01:34
Разобрался.
При создании м2м связи джанга проверяет есть ли такая запись, и если есть то удаляет её.

django/db/models/fields/related.py

Код

def _clear_items(self, source_field_name):            
    db = router.db_for_write(self.through, instance=self.instance)
    # source_field_name: the PK colname in join table for the source object
    if self.reverse or source_field_name == self.source_field_name:
        # Don't send the signal when we are clearing the
        # duplicate data rows for symmetrical reverse entries.
        signals.m2m_changed.send(sender=self.through, action="pre_clear",
            instance=self.instance, reverse=self.reverse,
            model=self.model, pk_set=None, using=db)
    self.through._default_manager.using(db).filter(**{
        source_field_name: self._pk_val}).delete()
    if self.reverse or source_field_name == self.source_field_name:
        # Don't send the signal when we are clearing the
        # duplicate data rows for symmetrical reverse entries.
        signals.m2m_changed.send(sender=self.through, action="post_clear",
            instance=self.instance, reverse=self.reverse,
            model=self.model, pk_set=None, using=db)


Инсерт прописал в сигнал m2m_changed, action="post_clear"

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)