class Title(models.Model): language = models.CharField(_("language"), max_length=15, db_index=True) title = models.CharField(_("title"), max_length=255) menu_title = models.CharField(_("title"), max_length=255, blank=True, null=True, help_text=_("overwrite the title in the menu")) slug = models.SlugField(_("slug"), max_length=255, db_index=True, unique=False) path = models.CharField(_("Path"), max_length=255, db_index=True) has_url_overwrite = models.BooleanField(_("has url overwrite"), default=False, db_index=True, editable=False) application_urls = models.CharField(_('application'), max_length=200, blank=True, null=True, db_index=True) redirect = models.CharField(_("redirect"), max_length=255, blank=True, null=True) meta_description = models.TextField(_("description"), max_length=255, blank=True, null=True) meta_keywords = models.CharField(_("keywords"), max_length=255, blank=True, null=True) page_title = models.CharField(_("title"), max_length=255, blank=True, null=True, help_text=_("overwrite the title (html title tag)")) page = models.ForeignKey(Page, verbose_name=_("page"), related_name="title_set") creation_date = models.DateTimeField(_("creation date"), editable=False, default=datetime.now) objects = TitleManager() class Meta: unique_together = (('language', 'page'),) app_label = 'cms' def __unicode__(self): return "%s (%s)" % (self.title, self.slug) def save(self, *args, **kwargs): # Build path from parent page's path and slug current_path = self.path parent_page = self.page.parent slug = u'%s' % self.slug if not self.has_url_overwrite: self.path = u'%s' % slug if parent_page: parent_title = Title.objects.get_title(parent_page, language=self.language, language_fallback=True) if parent_title: self.path = u'%s/%s' % (parent_title.path, slug) super(Title, self).save(*args, **kwargs) @property def overwrite_url(self): """Return overrwriten url, or None """ if self.has_url_overwrite: return self.path return None
class Title(models.Model): language = models.CharField(_("language"), max_length=15, db_index=True) title = models.CharField(_("title"), max_length=255) page_title = models.CharField( _("title"), max_length=255, blank=True, null=True, help_text=_("overwrite the title (html title tag)")) menu_title = models.CharField( _("title"), max_length=255, blank=True, null=True, help_text=_("overwrite the title in the menu")) meta_description = models.TextField( _("description"), max_length=320, blank=True, null=True, help_text=_("The text displayed in search engines.")) slug = models.SlugField(_("slug"), max_length=255, db_index=True, unique=False) path = models.CharField(_("Path"), max_length=255, db_index=True) has_url_overwrite = models.BooleanField(_("has url overwrite"), default=False, db_index=True, editable=False) redirect = models.CharField(_("redirect"), max_length=2048, blank=True, null=True) page = models.ForeignKey(Page, verbose_name=_("page"), related_name="title_set") creation_date = models.DateTimeField(_("creation date"), editable=False, default=timezone.now) # Publisher fields published = models.BooleanField(_("is published"), blank=True, default=False) publisher_is_draft = models.BooleanField(default=True, editable=False, db_index=True) # This is misnamed - the one-to-one relation is populated on both ends publisher_public = models.OneToOneField('self', related_name='publisher_draft', null=True, editable=False) publisher_state = models.SmallIntegerField(default=0, editable=False, db_index=True) objects = TitleManager() class Meta: unique_together = (('language', 'page'), ) app_label = 'cms' def __str__(self): return u"%s (%s, %s)" % (self.title, self.slug, self.language) def update_path(self): # Build path from parent page's path and slug slug = u'%s' % self.slug if not self.has_url_overwrite: self.path = u'%s' % slug if self.page.parent_id: parent_page = self.page.parent_id parent_title = Title.objects.get_title(parent_page, language=self.language, language_fallback=True) if parent_title: self.path = u'%s/%s' % (parent_title.path, slug) @property def overwrite_url(self): """Return overwritten url, or None """ if self.has_url_overwrite: return self.path return None def is_dirty(self): return self.publisher_state == PUBLISHER_STATE_DIRTY def save_base(self, *args, **kwargs): """Overridden save_base. If an instance is draft, and was changed, mark it as dirty. Dirty flag is used for changed nodes identification when publish method takes place. After current changes are published, state is set back to PUBLISHER_STATE_DEFAULT (in publish method). """ keep_state = getattr(self, '_publisher_keep_state', None) # Published pages should always have a publication date # if the page is published we set the publish date if not set yet. if self.page.publication_date is None and self.published: self.page.publication_date = timezone.now() - timedelta(seconds=5) if self.publisher_is_draft and not keep_state and self.is_new_dirty(): self.publisher_state = PUBLISHER_STATE_DIRTY if keep_state: delattr(self, '_publisher_keep_state') ret = super(Title, self).save_base(*args, **kwargs) return ret def is_new_dirty(self): if self.pk: fields = [ 'title', 'page_title', 'menu_title', 'meta_description', 'slug', 'has_url_overwrite', 'redirect' ] try: old_title = Title.objects.get(pk=self.pk) except Title.DoesNotExist: return True for field in fields: old_val = getattr(old_title, field) new_val = getattr(self, field) if not old_val == new_val: return True return False return True
class Title(models.Model): # These are the fields whose values are compared when saving # a Title object to know if it has changed. editable_fields = [ 'title', 'slug', 'redirect', 'page_title', 'menu_title', 'meta_description', 'has_url_overwrite', ] language = models.CharField(_("language"), max_length=15, db_index=True) title = models.CharField(_("title"), max_length=255) page_title = models.CharField( _("title"), max_length=255, blank=True, null=True, help_text=_("overwrite the title (html title tag)")) menu_title = models.CharField( _("title"), max_length=255, blank=True, null=True, help_text=_("overwrite the title in the menu")) meta_description = models.TextField( _("description"), max_length=155, blank=True, null=True, help_text=_("The text displayed in search engines.")) slug = models.SlugField(_("slug"), max_length=255, db_index=True, unique=False) path = models.CharField(_("Path"), max_length=255, db_index=True) has_url_overwrite = models.BooleanField(_("has url overwrite"), default=False, db_index=True, editable=False) redirect = models.CharField(_("redirect"), max_length=2048, blank=True, null=True) page = models.ForeignKey(Page, verbose_name=_("page"), related_name="title_set") creation_date = models.DateTimeField(_("creation date"), editable=False, default=timezone.now) # Publisher fields published = models.BooleanField(_("is published"), blank=True, default=False) publisher_is_draft = models.BooleanField(default=True, editable=False, db_index=True) # This is misnamed - the one-to-one relation is populated on both ends publisher_public = models.OneToOneField('self', related_name='publisher_draft', null=True, editable=False) publisher_state = models.SmallIntegerField(default=0, editable=False, db_index=True) objects = TitleManager() class Meta: unique_together = (('language', 'page'), ) app_label = 'cms' def __str__(self): return u"%s (%s, %s)" % (self.title, self.slug, self.language) def __repr__(self): display = '<{module}.{class_name} id={id} is_draft={is_draft} object at {location}>'.format( module=self.__module__, class_name=self.__class__.__name__, id=self.pk, is_draft=self.publisher_is_draft, location=hex(id(self)), ) return display def update_path(self): # Build path from parent page's path and slug slug = u'%s' % self.slug if not self.has_url_overwrite: self.path = u'%s' % slug if self.page.parent_id: parent_page = self.page.parent_id parent_title = Title.objects.get_title(parent_page, language=self.language, language_fallback=True) if parent_title: self.path = u'%s/%s' % (parent_title.path, slug) @property def overwrite_url(self): """Return overwritten url, or None """ if self.has_url_overwrite: return self.path return None def is_dirty(self): return self.publisher_state == PUBLISHER_STATE_DIRTY def save_base(self, *args, **kwargs): """Overridden save_base. If an instance is draft, and was changed, mark it as dirty. Dirty flag is used for changed nodes identification when publish method takes place. After current changes are published, state is set back to PUBLISHER_STATE_DEFAULT (in publish method). """ keep_state = getattr(self, '_publisher_keep_state', None) if self.publisher_is_draft and not keep_state and self.is_new_dirty(): self.publisher_state = PUBLISHER_STATE_DIRTY if keep_state: delattr(self, '_publisher_keep_state') return super(Title, self).save_base(*args, **kwargs) def is_new_dirty(self): if not self.pk: return True try: old_title = Title.objects.get(pk=self.pk) except Title.DoesNotExist: return True for field in self.editable_fields: old_val = getattr(old_title, field) new_val = getattr(self, field) if not old_val == new_val: return True if old_title.path != self.path and self.has_url_overwrite: # path is handled individually because its a special field. # The path field is both an internal and user facing field, # as such we can't mark the title as dirty on any change, # instead we need to check if the url overwrite flag is set. return True return False
class Title(Publisher): language = models.CharField(_("language"), max_length=5, db_index=True) title = models.CharField(_("title"), max_length=255) menu_title = models.CharField( _("title"), max_length=255, blank=True, null=True, help_text=_("overwrite the title in the menu")) slug = models.SlugField(_("slug"), max_length=255, db_index=True, unique=False) path = models.CharField(_("Path"), max_length=255, db_index=True) has_url_overwrite = models.BooleanField(_("has url overwrite"), default=False, db_index=True, editable=False) application_urls = models.CharField(_('application'), max_length=200, choices=settings.CMS_APPLICATIONS_URLS, blank=True, null=True, db_index=True) redirect = models.CharField(_("redirect"), max_length=255, blank=True, null=True) meta_description = models.TextField(_("description"), max_length=255, blank=True, null=True) meta_keywords = models.CharField(_("keywords"), max_length=255, blank=True, null=True) page_title = models.CharField( _("title"), max_length=255, blank=True, null=True, help_text=_("overwrite the title (html title tag)")) page = models.ForeignKey(Page, verbose_name=_("page"), related_name="title_set") creation_date = models.DateTimeField(_("creation date"), editable=False, default=datetime.now) objects = TitleManager() class Meta: unique_together = (('publisher_is_draft', 'language', 'page'), ) app_label = 'cms' def __unicode__(self): return "%s (%s)" % (self.title, self.slug) def save(self, **kwargs): # Build path from parent page's path and slug current_path = self.path parent_page = self.page.parent slug = u'%s' % self.slug if not self.has_url_overwrite: self.path = u'%s' % slug if parent_page: parent_title = Title.objects.get_title(parent_page, language=self.language, language_fallback=True) if parent_title: self.path = u'%s/%s' % (parent_title.path, slug) super(Title, self).save(**kwargs) # Update descendants only if path changed if current_path != self.path: descendant_titles = Title.objects.filter( page__lft__gt=self.page.lft, page__rght__lt=self.page.rght, page__tree_id__exact=self.page.tree_id, language=self.language) for descendant_title in descendant_titles: descendant_title.path = descendant_title.path.replace( current_path, self.path, 1) descendant_title.save() @property def overwrite_url(self): """Return overrwriten url, or None """ if self.has_url_overwrite: return self.path return None
class Title(models.Model): language = models.CharField(_("language"), max_length=15, db_index=True) title = models.CharField(_("title"), max_length=255) page_title = models.CharField( _("title"), max_length=255, blank=True, null=True, help_text=_("overwrite the title (html title tag)")) menu_title = models.CharField( _("title"), max_length=255, blank=True, null=True, help_text=_("overwrite the title in the menu")) meta_description = models.TextField( _("description"), max_length=155, blank=True, null=True, help_text=_("The text displayed in search engines.")) slug = models.SlugField(_("slug"), max_length=255, db_index=True, unique=False) path = models.CharField(_("Path"), max_length=255, db_index=True) has_url_overwrite = models.BooleanField(_("has url overwrite"), default=False, db_index=True, editable=False) redirect = models.CharField(_("redirect"), max_length=255, blank=True, null=True) page = models.ForeignKey(Page, verbose_name=_("page"), related_name="title_set") creation_date = models.DateTimeField(_("creation date"), editable=False, default=timezone.now) objects = TitleManager() class Meta: unique_together = (('language', 'page'), ) app_label = 'cms' def __str__(self): return u"%s (%s, %s)" % (self.title, self.slug, self.language) def update_path(self): # Build path from parent page's path and slug slug = u'%s' % self.slug if not self.has_url_overwrite: self.path = u'%s' % slug if self.page.parent_id: parent_page = self.page.parent_id parent_title = Title.objects.get_title(parent_page, language=self.language, language_fallback=True) if parent_title: self.path = u'%s/%s' % (parent_title.path, slug) @property def overwrite_url(self): """Return overwritten url, or None """ if self.has_url_overwrite: return self.path return None