Django — как добавить значение в ManyToManyField через админку?

Всем привет. Сразу к делу. Есть модели:



class Tag(models.Model):<br>
    name = models.CharField(verbose_name=u'Tag', max_length=200, unique=True)<br><br>
class Entry(models.Model):<br>
    title = models.CharField(verbose_name=u'Entry title', max_length=200)<br>
    # всякие поля<br>
    tags_string = models.CharField(verbose_name=u'Tags', max_length=200, blank=True)<br>
    tags = models.ManyToManyField(Tag, null=True, blank=True)<br>




В админке заполняется поле tags_string, которое на выходе выглядит например так: «cat, dog, pig»

Затем, я разбираю строку и добавляю тэги в таблицу Tag.

Задача в том, чтобы добавить связь между Entry и Tag. Другими словами, чтобы у поста были тэги.



Пытаюсь решить следующим образом:



def save(self):<br>
    super(Entry, self).save()<br>
    if self.tags_string:<br>
        for tag in tags_string.split(","):<br>
            t = Tag.objects.create(name=tag.lstrip())<br>
            self.tags.add(t)<br>




Тэги добавляются в таблицу, но таблица связей остается пуста.

Точно такая же операция, выполненная через джанговский shell срабатывает на ура. Я так полагаю, с методом save() не всё так просто. Есть идеи?



P.S. Самое интересное что связи не добавляются даже если написать вот так:

def save(self):<br>
    super(Entry, self).save()<br>
    self.tags.add(3) # где 3 - id тэга.<br>


хотя через тот же shell всё ок.



Заранее благодарю за помощь.
  • Вопрос задан
  • 8062 просмотра
Решения вопроса 1
summerisgone
@summerisgone
Беда твоя в админке. Автоматическое поле для tags автоматически тэги удаляет.
Если можно в твоей ситуации это поле безболезненно удалить, советую это сделать.

Ну и помощь:
class Tag(models.Model):
    name = models.CharField(verbose_name=u'Tag', max_length=200, unique=True)
 
    def __unicode__(self):
        return self.name
 
class Entry(models.Model):
    title = models.CharField(verbose_name=u'Entry title', max_length=200)
    tags_string = models.CharField(verbose_name=u'Tags', max_length=200, blank=True)
    # Обрати внимание на editable=False
    tags = models.ManyToManyField(Tag, null=True, blank=True, editable=False)
 
    def __init__(self*args, **kwargs):
        super(Entry, self).__init__(*args, **kwargs)
        # Инициализируем строку ``tags_string`` значениями тэгов
        if self.pk:
            self.tags_string = ', '.join(self.tags.values_list('name', flat=True))
 
    def save(self*args, **kwds):
        super(Entry, self).save(*args, **kwds)
 
        names = set([name.strip() for name in self.tags_string.split(',')])
        current = set(self.tags.values_list('name', flat=True))
        # Не только добавляй, но и удаляй тэги
        exclude = current - names
 
        for name in names:
            tag, created = Tag.objects.get_or_create(name=name)
            self.tags.add(tag)
        for name in exclude:
            tag = Tag.objects.get(name=name)
            self.tags.remove(tag)
 

админка:
class EntryAdmin(admin.ModelAdmin):
    model = Entry
    list_display = ('title''tag_list')
 
    def tag_list(self, obj):
        return ', '.join(obj.tags.values_list('name', flat=True))
 
admin.site.register(Entry, EntryAdmin)


И не хочешь ли ты использовать django-taggit или django-tagging?
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
elky
@elky Автор вопроса
Большое спасибо, дружище!

И не хочешь ли ты использовать django-taggit или django-tagging?

Да вот захотел своё.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы