Skip to content

Commit

Permalink
Improve meta
Browse files Browse the repository at this point in the history
* Made HTML description and title fields length configurable
* Added meta representation for CategoryEntriesView
  • Loading branch information
yakky committed Jan 8, 2018
1 parent bdfbfc4 commit a47b083
Show file tree
Hide file tree
Showing 10 changed files with 209 additions and 44 deletions.
4 changes: 3 additions & 1 deletion HISTORY.rst
Expand Up @@ -22,7 +22,9 @@ History
* Improved admin filtering.
* Added featured date to post.
* Fixed issue with urls in sitemap if apphook is not published
* Use the easy_thumbnails_tags template tag. Require easy_thumbnails >= 2.4.1
* Moved template to easy_thumbnails_tags template tag. Require easy_thumbnails >= 2.4.1
* Made HTML description and title fields length configurable
* Added meta representation for CategoryEntriesView


*******************
Expand Down
11 changes: 0 additions & 11 deletions djangocms_blog/admin.py
Expand Up @@ -6,7 +6,6 @@
from aldryn_apphooks_config.admin import BaseAppHookConfig, ModelAppHookConfig
from cms.admin.placeholderadmin import FrontendEditableAdminMixin, PlaceholderAdminMixin
from cms.models import CMSPlugin, ValidationError
from django import forms
from django.apps import apps
from django.conf import settings
from django.conf.urls import url
Expand Down Expand Up @@ -268,16 +267,6 @@ def publish_post(self, request, pk):
except KeyError:
return HttpResponseRedirect(reverse('djangocms_blog:posts-latest'))

def formfield_for_dbfield(self, db_field, **kwargs):
field = super(PostAdmin, self).formfield_for_dbfield(db_field, **kwargs)
if db_field.name == 'meta_description':
original_attrs = field.widget.attrs
original_attrs['maxlength'] = 160
field.widget = forms.TextInput(original_attrs)
elif db_field.name == 'meta_title':
field.max_length = 70
return field

def has_restricted_sites(self, request):
"""
Whether the current user has permission on one site only
Expand Down
26 changes: 26 additions & 0 deletions djangocms_blog/forms.py
Expand Up @@ -3,15 +3,28 @@

from django import forms
from django.conf import settings
from django.core.validators import MaxLengthValidator
from parler.forms import TranslatableModelForm
from taggit_autosuggest.widgets import TagAutoSuggest

from djangocms_blog.settings import get_setting

from .models import BlogCategory, BlogConfig, Post


class CategoryAdminForm(TranslatableModelForm):

def __init__(self, *args, **kwargs):
self.base_fields['meta_description'].validators = [
MaxLengthValidator(get_setting('META_DESCRIPTION_LENGTH'))
]
original_attrs = self.base_fields['meta_description'].widget.attrs
if 'cols' in original_attrs:
del original_attrs['cols']
if 'rows' in original_attrs:
del original_attrs['rows']
original_attrs['maxlength'] = get_setting('META_DESCRIPTION_LENGTH')
self.base_fields['meta_description'].widget = forms.TextInput(original_attrs)
super(CategoryAdminForm, self).__init__(*args, **kwargs)

if 'parent' in self.fields:
Expand Down Expand Up @@ -52,6 +65,19 @@ class Meta:
fields = '__all__'

def __init__(self, *args, **kwargs):
self.base_fields['meta_description'].validators = [
MaxLengthValidator(get_setting('META_DESCRIPTION_LENGTH'))
]
original_attrs = self.base_fields['meta_description'].widget.attrs
if 'cols' in original_attrs:
del original_attrs['cols']
if 'rows' in original_attrs:
del original_attrs['rows']
original_attrs['maxlength'] = get_setting('META_DESCRIPTION_LENGTH')
self.base_fields['meta_description'].widget = forms.TextInput(original_attrs)
self.base_fields['meta_title'].validators = [
MaxLengthValidator(get_setting('META_TITLE_LENGTH'))
]
super(PostAdminForm, self).__init__(*args, **kwargs)

qs = BlogCategory.objects
Expand Down
46 changes: 46 additions & 0 deletions djangocms_blog/migrations/0032_auto_20180109_0023.py
@@ -0,0 +1,46 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.8 on 2018-01-08 23:23
from __future__ import unicode_literals

from django.db import migrations, models
import djangocms_blog.fields


class Migration(migrations.Migration):

dependencies = [
('djangocms_blog', '0031_auto_20170610_1744'),
]

operations = [
migrations.AddField(
model_name='blogcategorytranslation',
name='meta_description',
field=models.TextField(blank=True, default='', verbose_name='post meta description'),
),
migrations.AlterField(
model_name='blogcategorytranslation',
name='name',
field=models.CharField(max_length=2000, verbose_name='name'),
),
migrations.AlterField(
model_name='blogcategorytranslation',
name='slug',
field=models.SlugField(blank=True, max_length=2000, verbose_name='slug'),
),
migrations.AlterField(
model_name='posttranslation',
name='meta_title',
field=models.CharField(blank=True, default='', help_text='used in title tag and social sharing', max_length=2000, verbose_name='post meta title'),
),
migrations.AlterField(
model_name='posttranslation',
name='slug',
field=djangocms_blog.fields.AutoSlugField(allow_unicode=True, blank=True, db_index=False, max_length=2000, verbose_name='slug'),
),
migrations.AlterField(
model_name='posttranslation',
name='title',
field=models.CharField(max_length=2000, verbose_name='title'),
),
]
88 changes: 63 additions & 25 deletions djangocms_blog/models.py
Expand Up @@ -58,8 +58,27 @@ class KnockerModel(object):
pass


class BlogMetaMixin(ModelMeta):

def get_meta_attribute(self, param):
"""
Retrieves django-meta attributes from apphook config instance
:param param: django-meta attribute passed as key
"""
return self._get_meta_value(param, getattr(self.app_config, param)) or ''

def get_locale(self):
return self.get_current_language()

def get_full_url(self):
"""
Return the url with protocol and domain url
"""
return self.build_absolute_uri(self.get_absolute_url())


@python_2_unicode_compatible
class BlogCategory(TranslatableModel):
class BlogCategory(BlogMetaMixin, TranslatableModel):
"""
Blog category
"""
Expand All @@ -73,13 +92,38 @@ class BlogCategory(TranslatableModel):
)

translations = TranslatedFields(
name=models.CharField(_('name'), max_length=255),
slug=models.SlugField(_('slug'), max_length=255, blank=True, db_index=True),
name=models.CharField(_('name'), max_length=2000),
slug=models.SlugField(_('slug'), max_length=2000, blank=True, db_index=True),
meta_description=models.TextField(
verbose_name=_('category meta description'), blank=True, default=''
),
meta={'unique_together': (('language_code', 'slug'),)}
)

objects = AppHookConfigTranslatableManager()

_metadata = {
'title': 'get_title',
'description': 'get_description',
'og_description': 'get_description',
'twitter_description': 'get_description',
'gplus_description': 'get_description',
'locale': 'get_locale',
'object_type': 'get_meta_attribute',
'og_type': 'get_meta_attribute',
'og_app_id': 'get_meta_attribute',
'og_profile_id': 'get_meta_attribute',
'og_publisher': 'get_meta_attribute',
'og_author_url': 'get_meta_attribute',
'og_author': 'get_meta_attribute',
'twitter_type': 'get_meta_attribute',
'twitter_site': 'get_meta_attribute',
'twitter_author': 'get_meta_attribute',
'gplus_type': 'get_meta_attribute',
'gplus_author': 'get_meta_attribute',
'url': 'get_absolute_url',
}

class Meta:
verbose_name = _('blog category')
verbose_name_plural = _('blog categories')
Expand All @@ -105,9 +149,11 @@ def count_all_sites(self):
return self.linked_posts.published(current_site=False).count()

def get_absolute_url(self, lang=None):
if not lang:
if not lang or lang not in self.get_available_languages():
lang = get_language()
if self.has_translation(lang, ):
if not lang or lang not in self.get_available_languages():
lang = self.get_current_language()
if self.has_translation(lang):
slug = self.safe_translation_getter('slug', language_code=lang)
return reverse(
'%s:posts-category' % self.app_config.namespace,
Expand All @@ -131,9 +177,17 @@ def save(self, *args, **kwargs):
self.slug = slugify(force_text(self.name))
self.save_translations()

def get_title(self):
title = self.safe_translation_getter('name', any_language=True)
return title.strip()

def get_description(self):
description = self.safe_translation_getter('meta_description', any_language=True)
return escape(strip_tags(description)).strip()


@python_2_unicode_compatible
class Post(KnockerModel, ModelMeta, TranslatableModel):
class Post(KnockerModel, BlogMetaMixin, TranslatableModel):
"""
Blog post
"""
Expand Down Expand Up @@ -173,8 +227,8 @@ class Post(KnockerModel, ModelMeta, TranslatableModel):
)

translations = TranslatedFields(
title=models.CharField(_('title'), max_length=255),
slug=AutoSlugField(_('slug'), max_length=255, blank=True,
title=models.CharField(_('title'), max_length=2000),
slug=AutoSlugField(_('slug'), max_length=2000, blank=True,
db_index=True, allow_unicode=True),
abstract=HTMLField(_('abstract'), blank=True, default=''),
meta_description=models.TextField(verbose_name=_('post meta description'),
Expand All @@ -183,7 +237,7 @@ class Post(KnockerModel, ModelMeta, TranslatableModel):
blank=True, default=''),
meta_title=models.CharField(verbose_name=_('post meta title'),
help_text=_('used in title tag and social sharing'),
max_length=255,
max_length=2000,
blank=True, default=''),
post_text=HTMLField(_('text'), default='', blank=True),
meta={'unique_together': (('language_code', 'slug'),)}
Expand Down Expand Up @@ -300,13 +354,6 @@ def get_absolute_url(self, lang=None):
kwargs['category'] = category.safe_translation_getter('slug', language_code=lang, any_language=True) # NOQA
return reverse('%s:post-detail' % self.app_config.namespace, kwargs=kwargs)

def get_meta_attribute(self, param):
"""
Retrieves django-meta attributes from apphook config instance
:param param: django-meta attribute passed as key
"""
return self._get_meta_value(param, getattr(self.app_config, param)) or ''

def get_title(self):
title = self.safe_translation_getter('meta_title', any_language=True)
if not title:
Expand All @@ -320,9 +367,6 @@ def get_keywords(self):
"""
return self.safe_translation_getter('meta_keywords', default='').strip().split(',')

def get_locale(self):
return self.get_current_language()

def get_description(self):
description = self.safe_translation_getter('meta_description', any_language=True)
if not description:
Expand Down Expand Up @@ -367,12 +411,6 @@ def full_image_options(self):
else:
return get_setting('IMAGE_FULL_SIZE')

def get_full_url(self):
"""
Return the url with protocol and domain url
"""
return self.build_absolute_uri(self.get_absolute_url())

@property
def is_published(self):
"""
Expand Down
6 changes: 6 additions & 0 deletions djangocms_blog/settings.py
Expand Up @@ -58,6 +58,12 @@ def get_setting(name):
'BLOG_POSTS_LIST_TRUNCWORDS_COUNT': getattr(
settings, 'BLOG_POSTS_LIST_TRUNCWORDS_COUNT', 100
),
'BLOG_META_DESCRIPTION_LENGTH': getattr(
settings, 'BLOG_META_DESCRIPTION_LENGTH', 320
),
'BLOG_META_TITLE_LENGTH': getattr(
settings, 'BLOG_META_TITLE_LENGTH', 70
),
'BLOG_MENU_TYPES': MENU_TYPES,
'BLOG_MENU_EMPTY_CATEGORIES': getattr(settings, 'MENU_EMPTY_CATEGORIES', True),
'BLOG_TYPE': getattr(settings, 'BLOG_TYPE', 'Article'),
Expand Down
1 change: 1 addition & 0 deletions djangocms_blog/views.py
Expand Up @@ -201,4 +201,5 @@ def get_queryset(self):
def get_context_data(self, **kwargs):
kwargs['category'] = self.category
context = super(CategoryEntriesView, self).get_context_data(**kwargs)
context['meta'] = self.category.as_meta()
return context
2 changes: 2 additions & 0 deletions docs/settings.rst
Expand Up @@ -92,6 +92,8 @@ Global Settings
* BLOG_FEED_LATEST_ITEMS: Number of items in latest items feed
* BLOG_FEED_TAGS_ITEMS: Number of items in per tags feed
* BLOG_PLUGIN_TEMPLATE_FOLDERS: (Sub-)folder from which the plugin templates are loaded. The default folder is ``plugins``. It goes into the ``djangocms_blog`` template folder (or, if set, the folder named in the app hook). This allows, e.g., different templates for showing a post list as tables, columns, ... . New templates have the same names as the standard templates in the ``plugins`` folder (``latest_entries.html``, ``authors.html``, ``tags.html``, ``categories.html``, ``archive.html``). Default behavior corresponds to this setting being ``( ("plugins", _("Default template") )``. To add new templates add to this setting, e.g., ``('timeline', _('Vertical timeline') )``.
* BLOG_META_DESCRIPTION_LENGTH: Maximum length for the Meta description field (default: ``320``)
* BLOG_META_TITLE_LENGTH: Maximum length for the Meta title field (default: ``70``)


******************
Expand Down

0 comments on commit a47b083

Please sign in to comment.