Уведомления

Группа в Telegram: @pythonsu
  • Начало
  • » Django
  • » Правильно переопределить save в моделе. [RSS Feed]

#1 Июль 25, 2013 11:06:41

agryn
От: Украина
Зарегистрирован: 2011-12-14
Сообщения: 189
Репутация: +  0  -
Профиль   Отправить e-mail  

Правильно переопределить save в моделе.

В моей моделе для новостей сделал дополнительное поле content_preview - неформатированый plain text для предварительного просмотра начала новости. Хочу переопределить метод save для того что б во время сохранения (вызова метода save) в это поле заносились необходимые данные. В качестве хранения текста новости использую markdown соотвецтвенно данные храняться в MarkupField. Когда я попробовал сделать так:

# -*- coding: utf-8 -*-
from django.db import models
from markitup.fields import MarkupField
from django.template.defaultfilters import striptags
class Source(models.Model):
    """
    Модель для опису джерел отримання новин
    """
    name = models.CharField("Джерело", max_length=200, help_text='назва джерела новин')
    name_full = models.CharField("Джерело (повна назва)", blank=True, max_length=600, help_text='повна назва джерела новин')
    site = models.URLField("Сайт", help_text='сайт джерела інформації')
    def __unicode__(self):
        return self.name
    class Meta:
        verbose_name = 'Джерело новини'
        verbose_name_plural = 'Джерела новин'
class Article(models.Model):
    """
    Модель для новин
    """
    title = models.CharField("Заголовок", max_length=200)
    content_preview = models.TextField("Попередній текст", editable=False, blank=True, help_text='Початокова частина статті (неформатований plain текст генеруэться з markdown)')
    content = MarkupField("Cтаття в markdown", help_text='Текст статті в розмітці markdown')
    orig_date = models.DateTimeField("Дата оригінальної публікації", default=None, null=True, blank=True, help_text='Дата публікації в оригіналі статті')
    pars_date = models.DateTimeField("Дата парсинга", editable=False, default=None, null=True, blank=True, help_text='Дата коли стаття була добавлеа парсером в БД')
    site_date = models.DateTimeField("Дата публікації", help_text='Дата публыкації що буде відображатись на нашому сайті')
    author = models.CharField("Автор статті", max_length=50, blank=True, help_text='Автор з оригінальної статті') ## автор статті з
    orig_url = models.URLField("URL посилання", blank=True)
    source = models.ForeignKey(Source)
    is_published = models.BooleanField("Публікація")
    def save(self, *args, **kwargs):
        self.content_preview = striptags(self.content._get_rendered())
        super(Article, self).save(*args, **kwargs)
        
    def __unicode__(self):
        return self.title
    class Meta:
        verbose_name = 'Новина'
        verbose_name_plural = 'Новини'
        ordering = ['-site_date']
то данные в поле content_preview обновляються только при повторном вызове save.
Подскажите как правильно сгенерировать данные в поле content_preview

Офлайн

#2 Июль 26, 2013 06:57:09

ilnur
От: Казань
Зарегистрирован: 2009-01-06
Сообщения: 524
Репутация: +  22  -
Профиль   Отправить e-mail  

Правильно переопределить save в моделе.

не совсем понял.
опишите ситуацию. Делаю так мол так, а вот это не получается.

Офлайн

#3 Июль 26, 2013 10:19:36

agryn
От: Украина
Зарегистрирован: 2011-12-14
Сообщения: 189
Репутация: +  0  -
Профиль   Отправить e-mail  

Правильно переопределить save в моделе.

ilnur
не совсем понял.опишите ситуацию. Делаю так мол так, а вот это не получается.
При создании новой записи через админку, с использованием описанной выше модели, поле content_preview не обновляется. А я хочу чтоб в это поле автоматом заносились данные при нажатии кнопки “Сохранить” в админке.

Отредактировано agryn (Июль 26, 2013 10:32:23)

Офлайн

#4 Июль 26, 2013 13:00:30

ilnur
От: Казань
Зарегистрирован: 2009-01-06
Сообщения: 524
Репутация: +  22  -
Профиль   Отправить e-mail  

Правильно переопределить save в моделе.

попробуй что-то своё туда записать.

def save(self, *args, **kwargs):
        self.content_preview = u'тестовый текст'
        super(Article, self).save(*args, **kwargs)
может self.content._get_rendered() возвращает пустоту

Офлайн

#5 Июль 26, 2013 13:58:46

agryn
От: Украина
Зарегистрирован: 2011-12-14
Сообщения: 189
Репутация: +  0  -
Профиль   Отправить e-mail  

Правильно переопределить save в моделе.

ilnur
попробуй что-то своё туда записать.
Да self.content._get_rendered() возвращает пустоту и вообще все атрибуты модели в етом месте кода пустые, в том то и проблема что мне нужно вызвать s
elf.content_preview = striptags(self.content._get_rendered())
в тот момент когда атрибуты уже со значениями а комит(запись в БД) еще не произведен.
Как вариант вызвать после save (тогда уже точно все атрибуты екземпляра класа присвоены). Но тогда нужно повторный запрос к БД для записи/обновления (для меня повторный запрос не критичен). Я попробовал сделать это с помощью сигналов:
@receiver(post_save, sender = Article)
def generate_preview(instance, **kwargs):
    article = instance
    article.content_preview = striptags(article.content.rendered)
    article.save()
Но данная конструкция вызывает себя рекурсивно. А как сделать без рекурсии пока не дойду.

Офлайн

#6 Июль 26, 2013 14:48:55

ilnur
От: Казань
Зарегистрирован: 2009-01-06
Сообщения: 524
Репутация: +  22  -
Профиль   Отправить e-mail  

Правильно переопределить save в моделе.

у меня все нормально, в save передастся экземпляр модели с заполненными полями

class Category(models.Model):
    name = models.CharField(
        verbose_name='Название', 
        max_length=100)
    url = models.CharField(
        verbose_name='url',
        max_length=100,
        blank=True)
    def save(self, *args, **kwargs):
        self.url = self.name
        super(Category, self).save(*args, **kwargs)

Офлайн

#7 Июль 26, 2013 15:06:06

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Правильно переопределить save в моделе.

ilnur,
не горячись, попробуй то же самое сделать ближе к задаче ТСа, то есть тебе нужно реализовать

content_preview = models.TextField("", editable=False, blank=True, help_text='')
content = MarkupField("", help_text='')
def save(self, *args, **kwargs):
        self.content_preview = striptags(self.content._get_rendered())
        super(Article, self).save(*args, **kwargs)
чтобы убедиться в том, что ТС гонит
А ТС, судя по всему не совсем нуб и задает не пустой вопрос.

мне лень

agryn,
а что должен возвращать метод _get_rendered()?
Если не внутри сейва, а просто
foo = Article.objects.get(pk=1).content._get_rendered()
то что получается?



Офлайн

#8 Июль 26, 2013 17:23:13

agryn
От: Украина
Зарегистрирован: 2011-12-14
Сообщения: 189
Репутация: +  0  -
Профиль   Отправить e-mail  

Правильно переопределить save в моделе.

Article.objects.get(pk=1).content._get_rendered()
Возвращает отрендереный с markdowd html-код.
Вся соль вопроса в том что покопался в исходниках markitup я так и непонял на кокой стадии (а самое главное где в коде) производиться генерирование с markdowd-кода html-код.

Офлайн

#9 Июль 26, 2013 17:41:05

agryn
От: Украина
Зарегистрирован: 2011-12-14
Сообщения: 189
Репутация: +  0  -
Профиль   Отправить e-mail  

Правильно переопределить save в моделе.

Короче вопрос решил вот таким возможно не самым элегантным с точки зрения использования ресурсов (двойной запрос при сохранении записи в БД, а также generate_preview вызываеться рекурсивно один раз) но рабочим кодом:

from django.template.defaultfilters import striptags, truncatewords
from django.db.models.signals import post_save
from django.dispatch import receiver
...
@receiver(post_save, sender = Article)
def generate_preview(instance, **kwargs):
    content_preview = striptags(instance.content.rendered)
    content_preview = truncatewords(content_preview, 35)
    if instance.content_preview != content_preview:
        instance.content_preview = content_preview
        instance.save()

Отредактировано agryn (Июль 26, 2013 18:02:31)

Офлайн

  • Начало
  • » Django
  • » Правильно переопределить save в моделе.[RSS Feed]

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version