# -*- coding: utf-8 -*- from django.db import models from django.utils.timezone import now from filer.fields.image import FilerFileField from ckeditor.fields import RichTextField from web.add_function import safe_html_special_symbols import urllib3 import pytils import random # Create your models here. class TbContent(models.Model): # ============================================================ # ТАБЛИЦА TbContent (контент для всего-всего-всего) # ------------------------------------------------------------ # | id -- id | primarykey bigint NOT NULL AUTO_INCREMENT | # | kCategory_id -- категория (ссылка на таблицу TbCategory) | bigint DEFAULT NULL, # | bContentPublish -- имя файла | TINYINT(1) NOT NULL ADD INDEX | # | tdContentPublishStart -- начало публикации | date NOT NULL ADD INDEX | # | szContentHead -- заголовок | varchar(512) NOT NULL | # | imgContentPreview_id -- картинка превью (ссылка на таблицу filer_image) | bigint DEFAULT NULL ADD INDEX # | szContentAnno -- анонс | longtext NOT NULL, # | szContentBody -- содержание | longtext NOT NULL, # | bTypografS -- включить типограф Typograf 2.0 | tinyint(1) NOT NULL, # | szContentTitle -- title для SEO | longtext NOT NULL, # | szContentKeywords -- keywords для SEO | longtext NOT NULL, # | szContentDescription -- Description для SEO | longtext NOT NULL, # | dtContentCreate -- дата и время создания | datetime(6) NOT NULL, # | dtContentTimeStamp -- штамп времени (время последнего обновления в базе) | datetime(6) NOT NULL # ============================================================ bContentPublish = models.BooleanField( default=True, db_index=True, verbose_name="Опуб…", help_text="Опубликованный контент будет отображаться в соответствующей ленте категории и" " при его просмотре будет отображаться навигация &laque;Предыдущий&raque;" " и &laque;Следующий&raque; по ленте. По прямому URL (если его знать) " "отображается даже не опубликованный контент (но без навигации)." ) tdContentPublishStart = models.DateField( db_index=True, default=now, # datetime.date.today(), verbose_name="Дата публикации", help_text=u"Дата публикации, с её момента новость появится на сайте." ) szContentHead = models.CharField( max_length=512, default=u"", blank=False, null=False, verbose_name="Заголовок", help_text="Заголовок контента (допустим HTML-код, будет обработан типографом," " если его включить, максимальная длинна 512 символов)" ) imgContentPreview = FilerFileField( null=True, blank=True, on_delete=models.SET_NULL, related_name="Превью", verbose_name="Превью", help_text="Картинка-превью" ) szContentIntro = RichTextField( config_name='fine', default="", verbose_name="Анонс", help_text="Анонс (допустим HTML-код, будет обработан типографом," " если его включить)" ) szContentBody = RichTextField( config_name='fine', default="", verbose_name="Содержание", help_text="Содержание БЕЗ АНОНСА (допустим HTML-код, будет обработан типографом," " если его включить)" ) szContentSlug = models.CharField( default="", max_length=128, blank=True, null=True, verbose_name="Slug", help_text="Слуг… 128 символов.
Если оставить" " пустым, то slug сформируется автоматически" ) bTypograf = models.BooleanField( default=False, verbose_name="Типограф Стандарт", help_text="Обработать через Типограф 2.0
" "НОРМАЛЬНЫЙ ТИПОГРАФ, ХОРОШИЙ HTML, РЕКОМЕНДУЕМ
" "«приклеивает» союзы, поддерживает неразрывные конструкции,
" "замена тире, кавычек и дефисов, расстановка «мягких переносов»
" "в словах длиннее 12 символов, убирает «вдовы» «сироты» (кроме
" "заголовков), расставляет абзацы (кроме заголовков), расшифро-
" "вывает аббревиатуры (те, что знает и кроме заголовков), висячая
" "пунктуация (только в заголовках) и т.п.
" ) szContentKeywords = models.CharField( default="", max_length=256, blank=True, null=True, verbose_name="Keywords (SEO)", help_text="Ключевые слова. Через запятую. 256 символов." ) szContentDescription = models.CharField( default="", max_length=256, blank=True, null=True, verbose_name="Description (SEO)", help_text="Описание страницы… 256 символов (включая пробелы), но поисковики обработают только 155–160" " из них.
Если оставить пустым, то описание сформируется автоматически" " на базе заголовка и анонса" ) dtContentCreate = models.DateTimeField( auto_now_add=True, # надо указать False при миграции, после вернуть в True # для выполнения миграций нужно добавлять default, а после она не нужна # default=datetime.datetime.now(pytz.timezone(settings.TIME_ZONE)), verbose_name="Дата Создания" ) dtContentTimeStamp = models.DateTimeField( auto_now=True, # надо указать False при миграции, после вернуть в True # для выполнения миграций нужно добавлять default, а после она не нужна # default=datetime.datetime.now(pytz.timezone(settings.TIME_ZONE)), verbose_name="Штамп времени" ) def __unicode__(self): return u"%03d: %s (%s)" % (self.id, self.szContentHead[:30] + "…" if len(self.szContentHead) > 30 else self.szContentHead, str(self.kCategory)[:15] + "…" if len(str(self.kCategory)) > 15 else self.kCategory) def __str__(self): result = safe_html_special_symbols(self.szContentHead) return u"%03d: %s" % (self.id, result[:50] + "…" if len(result) > 50 else result) def save(self, *args, **kwargs): # переопределяем метод save() чтобы "проверуть" тексты через типографы... if self.szContentSlug is None or " " in self.szContentSlug: result_slug = pytils.translit.slugify( safe_html_special_symbols(self.szContentSlug)).lower() while TbContent.objects.filter(szContentSlug=result_slug).count() != 0: result_slug = "%s-%x" % (result_slug, int(random.uniform(0, 255))) self.szPointSlug = result_slug if self.bTypograf: # Используем типограф Eugene Spearance (https://www.typograf.ru) через API # Настройки стиля типографики см. тут: https://www.typograf.ru/webservice/about/ try: http = urllib3.PoolManager() resp = http.request("POST", "https://www.typograf.ru/webservice/", fields={"text": self.szContentHead.encode('cp1251'), 'xml': '' '' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ''.encode('cp1251')}) result = resp.data.decode('cp1251') if len(result) <= 512: self.szContentHead = result resp = http.request("POST", "https://www.typograf.ru/webservice/", fields={"text": self.szContentIntro.encode('cp1251'), 'xml': '' '' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ''.encode('cp1251')}) self.szContentIntro = resp.data.decode('cp1251') resp = http.request("POST", "https://www.typograf.ru/webservice/", fields={"text": self.szContentBody.encode('cp1251'), 'xml': '' '' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ''.encode('cp1251')}) self.szContentBody = resp.data.decode('cp1251') except: self.bTypograf = False super(TbContent, self).save(*args, **kwargs) class Meta: verbose_name = "Контент" verbose_name_plural = u"Контент" ordering = ['-tdContentPublishStart', ]