Merge pull request #410 from nephila/feature/improve_meta
Improved meta fields configuration
This commit is contained in:
commit
8c1660d84a
10 changed files with 209 additions and 44 deletions
|
|
@ -22,7 +22,9 @@ History
|
||||||
* Improved admin filtering.
|
* Improved admin filtering.
|
||||||
* Added featured date to post.
|
* Added featured date to post.
|
||||||
* Fixed issue with urls in sitemap if apphook is not published
|
* 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
|
||||||
|
|
||||||
|
|
||||||
*******************
|
*******************
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ from copy import deepcopy
|
||||||
from aldryn_apphooks_config.admin import BaseAppHookConfig, ModelAppHookConfig
|
from aldryn_apphooks_config.admin import BaseAppHookConfig, ModelAppHookConfig
|
||||||
from cms.admin.placeholderadmin import FrontendEditableAdminMixin, PlaceholderAdminMixin
|
from cms.admin.placeholderadmin import FrontendEditableAdminMixin, PlaceholderAdminMixin
|
||||||
from cms.models import CMSPlugin, ValidationError
|
from cms.models import CMSPlugin, ValidationError
|
||||||
from django import forms
|
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
|
|
@ -262,16 +261,6 @@ class PostAdmin(PlaceholderAdminMixin, FrontendEditableAdminMixin,
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return HttpResponseRedirect(reverse('djangocms_blog:posts-latest'))
|
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):
|
def has_restricted_sites(self, request):
|
||||||
"""
|
"""
|
||||||
Whether the current user has permission on one site only
|
Whether the current user has permission on one site only
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,28 @@ from __future__ import absolute_import, print_function, unicode_literals
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.core.validators import MaxLengthValidator
|
||||||
from parler.forms import TranslatableModelForm
|
from parler.forms import TranslatableModelForm
|
||||||
from taggit_autosuggest.widgets import TagAutoSuggest
|
from taggit_autosuggest.widgets import TagAutoSuggest
|
||||||
|
|
||||||
|
from djangocms_blog.settings import get_setting
|
||||||
|
|
||||||
from .models import BlogCategory, BlogConfig, Post
|
from .models import BlogCategory, BlogConfig, Post
|
||||||
|
|
||||||
|
|
||||||
class CategoryAdminForm(TranslatableModelForm):
|
class CategoryAdminForm(TranslatableModelForm):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
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)
|
super(CategoryAdminForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
if 'parent' in self.fields:
|
if 'parent' in self.fields:
|
||||||
|
|
@ -52,6 +65,19 @@ class PostAdminForm(TranslatableModelForm):
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
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)
|
super(PostAdminForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
qs = BlogCategory.objects
|
qs = BlogCategory.objects
|
||||||
|
|
|
||||||
46
djangocms_blog/migrations/0032_auto_20180109_0023.py
Normal file
46
djangocms_blog/migrations/0032_auto_20180109_0023.py
Normal file
|
|
@ -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'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -58,8 +58,27 @@ except ImportError:
|
||||||
pass
|
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
|
@python_2_unicode_compatible
|
||||||
class BlogCategory(TranslatableModel):
|
class BlogCategory(BlogMetaMixin, TranslatableModel):
|
||||||
"""
|
"""
|
||||||
Blog category
|
Blog category
|
||||||
"""
|
"""
|
||||||
|
|
@ -73,13 +92,38 @@ class BlogCategory(TranslatableModel):
|
||||||
)
|
)
|
||||||
|
|
||||||
translations = TranslatedFields(
|
translations = TranslatedFields(
|
||||||
name=models.CharField(_('name'), max_length=255),
|
name=models.CharField(_('name'), max_length=2000),
|
||||||
slug=models.SlugField(_('slug'), max_length=255, blank=True, db_index=True),
|
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'),)}
|
meta={'unique_together': (('language_code', 'slug'),)}
|
||||||
)
|
)
|
||||||
|
|
||||||
objects = AppHookConfigTranslatableManager()
|
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:
|
class Meta:
|
||||||
verbose_name = _('blog category')
|
verbose_name = _('blog category')
|
||||||
verbose_name_plural = _('blog categories')
|
verbose_name_plural = _('blog categories')
|
||||||
|
|
@ -105,9 +149,11 @@ class BlogCategory(TranslatableModel):
|
||||||
return self.linked_posts.published(current_site=False).count()
|
return self.linked_posts.published(current_site=False).count()
|
||||||
|
|
||||||
def get_absolute_url(self, lang=None):
|
def get_absolute_url(self, lang=None):
|
||||||
if not lang:
|
if not lang or lang not in self.get_available_languages():
|
||||||
lang = get_language()
|
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)
|
slug = self.safe_translation_getter('slug', language_code=lang)
|
||||||
return reverse(
|
return reverse(
|
||||||
'%s:posts-category' % self.app_config.namespace,
|
'%s:posts-category' % self.app_config.namespace,
|
||||||
|
|
@ -131,9 +177,17 @@ class BlogCategory(TranslatableModel):
|
||||||
self.slug = slugify(force_text(self.name))
|
self.slug = slugify(force_text(self.name))
|
||||||
self.save_translations()
|
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
|
@python_2_unicode_compatible
|
||||||
class Post(KnockerModel, ModelMeta, TranslatableModel):
|
class Post(KnockerModel, BlogMetaMixin, TranslatableModel):
|
||||||
"""
|
"""
|
||||||
Blog post
|
Blog post
|
||||||
"""
|
"""
|
||||||
|
|
@ -173,8 +227,8 @@ class Post(KnockerModel, ModelMeta, TranslatableModel):
|
||||||
)
|
)
|
||||||
|
|
||||||
translations = TranslatedFields(
|
translations = TranslatedFields(
|
||||||
title=models.CharField(_('title'), max_length=255),
|
title=models.CharField(_('title'), max_length=2000),
|
||||||
slug=AutoSlugField(_('slug'), max_length=255, blank=True,
|
slug=AutoSlugField(_('slug'), max_length=2000, blank=True,
|
||||||
db_index=True, allow_unicode=True),
|
db_index=True, allow_unicode=True),
|
||||||
abstract=HTMLField(_('abstract'), blank=True, default=''),
|
abstract=HTMLField(_('abstract'), blank=True, default=''),
|
||||||
meta_description=models.TextField(verbose_name=_('post meta description'),
|
meta_description=models.TextField(verbose_name=_('post meta description'),
|
||||||
|
|
@ -183,7 +237,7 @@ class Post(KnockerModel, ModelMeta, TranslatableModel):
|
||||||
blank=True, default=''),
|
blank=True, default=''),
|
||||||
meta_title=models.CharField(verbose_name=_('post meta title'),
|
meta_title=models.CharField(verbose_name=_('post meta title'),
|
||||||
help_text=_('used in title tag and social sharing'),
|
help_text=_('used in title tag and social sharing'),
|
||||||
max_length=255,
|
max_length=2000,
|
||||||
blank=True, default=''),
|
blank=True, default=''),
|
||||||
post_text=HTMLField(_('text'), default='', blank=True),
|
post_text=HTMLField(_('text'), default='', blank=True),
|
||||||
meta={'unique_together': (('language_code', 'slug'),)}
|
meta={'unique_together': (('language_code', 'slug'),)}
|
||||||
|
|
@ -300,13 +354,6 @@ class Post(KnockerModel, ModelMeta, TranslatableModel):
|
||||||
kwargs['category'] = category.safe_translation_getter('slug', language_code=lang, any_language=True) # NOQA
|
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)
|
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):
|
def get_title(self):
|
||||||
title = self.safe_translation_getter('meta_title', any_language=True)
|
title = self.safe_translation_getter('meta_title', any_language=True)
|
||||||
if not title:
|
if not title:
|
||||||
|
|
@ -320,9 +367,6 @@ class Post(KnockerModel, ModelMeta, TranslatableModel):
|
||||||
"""
|
"""
|
||||||
return self.safe_translation_getter('meta_keywords', default='').strip().split(',')
|
return self.safe_translation_getter('meta_keywords', default='').strip().split(',')
|
||||||
|
|
||||||
def get_locale(self):
|
|
||||||
return self.get_current_language()
|
|
||||||
|
|
||||||
def get_description(self):
|
def get_description(self):
|
||||||
description = self.safe_translation_getter('meta_description', any_language=True)
|
description = self.safe_translation_getter('meta_description', any_language=True)
|
||||||
if not description:
|
if not description:
|
||||||
|
|
@ -367,12 +411,6 @@ class Post(KnockerModel, ModelMeta, TranslatableModel):
|
||||||
else:
|
else:
|
||||||
return get_setting('IMAGE_FULL_SIZE')
|
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
|
@property
|
||||||
def is_published(self):
|
def is_published(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,12 @@ def get_setting(name):
|
||||||
'BLOG_POSTS_LIST_TRUNCWORDS_COUNT': getattr(
|
'BLOG_POSTS_LIST_TRUNCWORDS_COUNT': getattr(
|
||||||
settings, 'BLOG_POSTS_LIST_TRUNCWORDS_COUNT', 100
|
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_TYPES': MENU_TYPES,
|
||||||
'BLOG_MENU_EMPTY_CATEGORIES': getattr(settings, 'MENU_EMPTY_CATEGORIES', True),
|
'BLOG_MENU_EMPTY_CATEGORIES': getattr(settings, 'MENU_EMPTY_CATEGORIES', True),
|
||||||
'BLOG_TYPE': getattr(settings, 'BLOG_TYPE', 'Article'),
|
'BLOG_TYPE': getattr(settings, 'BLOG_TYPE', 'Article'),
|
||||||
|
|
|
||||||
|
|
@ -201,4 +201,5 @@ class CategoryEntriesView(BaseBlogListView, ListView):
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
kwargs['category'] = self.category
|
kwargs['category'] = self.category
|
||||||
context = super(CategoryEntriesView, self).get_context_data(**kwargs)
|
context = super(CategoryEntriesView, self).get_context_data(**kwargs)
|
||||||
|
context['meta'] = self.category.as_meta()
|
||||||
return context
|
return context
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,8 @@ Global Settings
|
||||||
* BLOG_FEED_LATEST_ITEMS: Number of items in latest items feed
|
* BLOG_FEED_LATEST_ITEMS: Number of items in latest items feed
|
||||||
* BLOG_FEED_TAGS_ITEMS: Number of items in per tags 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_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``)
|
||||||
|
|
||||||
|
|
||||||
******************
|
******************
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ from django.contrib.auth.models import AnonymousUser
|
||||||
from django.contrib.messages.middleware import MessageMiddleware
|
from django.contrib.messages.middleware import MessageMiddleware
|
||||||
from django.contrib.sites.models import Site
|
from django.contrib.sites.models import Site
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
|
from django.test import override_settings
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
from django.utils.html import strip_tags
|
from django.utils.html import strip_tags
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
|
|
@ -25,6 +26,7 @@ from parler.utils.context import smart_override
|
||||||
from taggit.models import Tag
|
from taggit.models import Tag
|
||||||
|
|
||||||
from djangocms_blog.cms_appconfig import BlogConfig, BlogConfigForm
|
from djangocms_blog.cms_appconfig import BlogConfig, BlogConfigForm
|
||||||
|
from djangocms_blog.forms import CategoryAdminForm, PostAdminForm
|
||||||
from djangocms_blog.models import BlogCategory, Post
|
from djangocms_blog.models import BlogCategory, Post
|
||||||
from djangocms_blog.settings import MENU_TYPE_NONE, get_setting
|
from djangocms_blog.settings import MENU_TYPE_NONE, get_setting
|
||||||
|
|
||||||
|
|
@ -80,12 +82,13 @@ class AdminTest(BaseTest):
|
||||||
|
|
||||||
# Add view only contains the apphook selection widget
|
# Add view only contains the apphook selection widget
|
||||||
response = post_admin.add_view(request)
|
response = post_admin.add_view(request)
|
||||||
self.assertNotContains(response, '<input id="id_slug" maxlength="255" name="slug" type="text"')
|
self.assertNotContains(response, '<input id="id_slug" maxlength="2000" name="slug" type="text"')
|
||||||
self.assertContains(response, '<option value="%s">Blog / sample_app</option>' % self.app_config_1.pk)
|
self.assertContains(response, '<option value="%s">Blog / sample_app</option>' % self.app_config_1.pk)
|
||||||
|
|
||||||
# Changeview is 'normal'
|
# Changeview is 'normal'
|
||||||
response = post_admin.change_view(request, str(post.pk))
|
response = post_admin.change_view(request, str(post.pk))
|
||||||
self.assertContains(response, '<input id="id_slug" maxlength="255" name="slug" type="text" value="first-post" />')
|
self.assertContains(response, '<input id="id_slug" maxlength="2000" name="slug" type="text" value="first-post" />')
|
||||||
|
self.assertContains(response, 'id="id_meta_description" maxlength="320"')
|
||||||
self.assertContains(response, '<option value="%s" selected="selected">Blog / sample_app</option>' % self.app_config_1.pk)
|
self.assertContains(response, '<option value="%s" selected="selected">Blog / sample_app</option>' % self.app_config_1.pk)
|
||||||
|
|
||||||
# Test for publish view
|
# Test for publish view
|
||||||
|
|
@ -176,19 +179,55 @@ class AdminTest(BaseTest):
|
||||||
self.assertContains(response, 'sample_app')
|
self.assertContains(response, 'sample_app')
|
||||||
|
|
||||||
def test_admin_category_views(self):
|
def test_admin_category_views(self):
|
||||||
post_admin = admin.site._registry[BlogCategory]
|
category_admin = admin.site._registry[BlogCategory]
|
||||||
request = self.get_page_request('/', self.user, r'/en/blog/', edit=False)
|
request = self.get_page_request('/', self.user, r'/en/blog/', edit=False)
|
||||||
|
|
||||||
# Add view only has an empty form - no type
|
# Add view only has an empty form - no type
|
||||||
response = post_admin.add_view(request)
|
response = category_admin.add_view(request)
|
||||||
self.assertNotContains(response, 'id="id_name" maxlength="255" name="name" type="text" value="category 1"')
|
self.assertNotContains(response, 'id="id_name" maxlength="2000" name="name" type="text" value="category 1"')
|
||||||
self.assertContains(response, '<option value="%s">Blog / sample_app</option>' % self.app_config_1.pk)
|
self.assertContains(response, '<option value="%s">Blog / sample_app</option>' % self.app_config_1.pk)
|
||||||
|
|
||||||
# Changeview is 'normal', with a few preselected items
|
# Changeview is 'normal', with a few preselected items
|
||||||
response = post_admin.change_view(request, str(self.category_1.pk))
|
response = category_admin.change_view(request, str(self.category_1.pk))
|
||||||
self.assertContains(response, 'id="id_name" maxlength="255" name="name" type="text" value="category 1"')
|
self.assertContains(response, 'id="id_name" maxlength="2000" name="name" type="text" value="category 1"')
|
||||||
|
self.assertContains(response, 'id="id_meta_description" maxlength="320"')
|
||||||
self.assertContains(response, '<option value="%s" selected="selected">Blog / sample_app</option>' % self.app_config_1.pk)
|
self.assertContains(response, '<option value="%s" selected="selected">Blog / sample_app</option>' % self.app_config_1.pk)
|
||||||
|
|
||||||
|
def test_form(self):
|
||||||
|
posts = self.get_posts()
|
||||||
|
with override_settings(BLOG_META_DESCRIPTION_LENGTH=20, BLOG_META_TITLE_LENGTH=20):
|
||||||
|
form = PostAdminForm(
|
||||||
|
data={'meta_description': 'major text over 20 characters long'},
|
||||||
|
instance=posts[0]
|
||||||
|
)
|
||||||
|
self.assertFalse(form.is_valid())
|
||||||
|
form = PostAdminForm(
|
||||||
|
data={'meta_title': 'major text over 20 characters long'},
|
||||||
|
instance=posts[0]
|
||||||
|
)
|
||||||
|
self.assertFalse(form.is_valid())
|
||||||
|
form = CategoryAdminForm(
|
||||||
|
data={'meta_description': 'major text over 20 characters long'},
|
||||||
|
instance=self.category_1
|
||||||
|
)
|
||||||
|
self.assertFalse(form.is_valid())
|
||||||
|
|
||||||
|
form = PostAdminForm(
|
||||||
|
data={'meta_description': 'mini text'},
|
||||||
|
instance=posts[0]
|
||||||
|
)
|
||||||
|
self.assertFalse(form.is_valid())
|
||||||
|
form = PostAdminForm(
|
||||||
|
data={'meta_title': 'mini text'},
|
||||||
|
instance=posts[0]
|
||||||
|
)
|
||||||
|
self.assertFalse(form.is_valid())
|
||||||
|
form = CategoryAdminForm(
|
||||||
|
data={'meta_description': 'mini text'},
|
||||||
|
instance=self.category_1
|
||||||
|
)
|
||||||
|
self.assertFalse(form.is_valid())
|
||||||
|
|
||||||
def test_admin_category_parents(self):
|
def test_admin_category_parents(self):
|
||||||
category1 = BlogCategory.objects.create(name='tree category 1', app_config=self.app_config_1)
|
category1 = BlogCategory.objects.create(name='tree category 1', app_config=self.app_config_1)
|
||||||
category2 = BlogCategory.objects.create(name='tree category 2', parent=category1, app_config=self.app_config_1)
|
category2 = BlogCategory.objects.create(name='tree category 2', parent=category1, app_config=self.app_config_1)
|
||||||
|
|
@ -618,6 +657,21 @@ class ModelsTest(BaseTest):
|
||||||
self.assertNotEqual(meta_it.title, meta_en.title)
|
self.assertNotEqual(meta_it.title, meta_en.title)
|
||||||
self.assertEqual(meta_it.description, post.meta_description)
|
self.assertEqual(meta_it.description, post.meta_description)
|
||||||
|
|
||||||
|
category = post.categories.first()
|
||||||
|
meta_cat = category.as_meta()
|
||||||
|
self.assertEqual(meta_cat.og_type, get_setting('FB_TYPE'))
|
||||||
|
self.assertEqual(meta_cat.title, category.name)
|
||||||
|
self.assertEqual(meta_cat.description, category.meta_description)
|
||||||
|
self.assertEqual(meta_cat.locale, 'en')
|
||||||
|
self.assertEqual(meta_cat.twitter_site, '')
|
||||||
|
self.assertEqual(meta_cat.twitter_author, '')
|
||||||
|
self.assertEqual(meta_cat.twitter_type, 'summary')
|
||||||
|
self.assertEqual(meta_cat.gplus_author, 'RandomJoe')
|
||||||
|
self.assertEqual(meta_cat.gplus_type, 'Blog')
|
||||||
|
self.assertEqual(meta_cat.og_type, 'Article')
|
||||||
|
self.assertEqual(meta_cat.facebook_app_id, None)
|
||||||
|
self.assertTrue(meta_cat.url.endswith(category.get_absolute_url()))
|
||||||
|
|
||||||
with override('en'):
|
with override('en'):
|
||||||
post.set_current_language(get_language())
|
post.set_current_language(get_language())
|
||||||
kwargs = {'year': post.date_published.year,
|
kwargs = {'year': post.date_published.year,
|
||||||
|
|
|
||||||
|
|
@ -254,6 +254,7 @@ class ViewTest(BaseTest):
|
||||||
self.assertEqual(list(context['post_list']), [posts[0]])
|
self.assertEqual(list(context['post_list']), [posts[0]])
|
||||||
self.assertEqual(context['paginator'].count, 3)
|
self.assertEqual(context['paginator'].count, 3)
|
||||||
self.assertEqual(context['post_list'][0].title, 'First post')
|
self.assertEqual(context['post_list'][0].title, 'First post')
|
||||||
|
self.assertTrue(context['meta'])
|
||||||
|
|
||||||
request = self.get_page_request(pages[1], self.user, edit=False)
|
request = self.get_page_request(pages[1], self.user, edit=False)
|
||||||
view_obj.request = request
|
view_obj.request = request
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue