From ae34ef70bb17d89a2cffda065e09a0f3c1fc35db Mon Sep 17 00:00:00 2001 From: Murat Aydos Date: Thu, 11 Dec 2014 18:27:39 +0200 Subject: [PATCH] Enable creating custom meta properties --- .gitignore | 2 ++ README.rst | 52 ++++++++++++++++++++++++++++- meta/templates/meta.html | 4 +++ meta/templatetags/meta.py | 13 ++++++++ meta/views.py | 24 ++++++++++++++ tests/test_meta.py | 4 +++ tests/test_metadata_mixin.py | 64 ++++++++++++++++++++++++++++++++++++ tests/test_templatetags.py | 30 ++++++++++++++++- 8 files changed, 191 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 6f4a5bf..d029d89 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ MANIFEST .idea .coverage *.egg-info + +*.iml diff --git a/README.rst b/README.rst index a9bcaf5..78545a6 100644 --- a/README.rst +++ b/README.rst @@ -71,6 +71,10 @@ following keys/attributes: + image + object_type + site_name ++ twitter_site ++ locale ++ meta_extras ++ meta_custom_extras In all cases, if the key is omitted, the matching metadata/property is not rendered. @@ -137,6 +141,46 @@ site_name This key is used to render the ``og:site_name`` property. +twitter_site +------------ + +This key is used to render the ``twitter:site`` property. + +locale +------ + +This key is used to render the ``og:locale`` property. + +meta_extras +----------- + +A dictionary of extra optional properties. + + { + 'foo': 'bar', + 'key': 'value' + } + + ... + + + + +custom_meta_extras +------------------ + +A list of tuples for rendering custom extra properties. + + [ + ('key', 'foo', 'bar') + ('property', 'name', 'value') + ] + + ... + + + + Meta objects ============ @@ -152,7 +196,13 @@ properties you want to use:: meta = Meta( title="Sam's awesome ponies", description='Awesome page about ponies', - keywords=['pony', 'ponies', 'awesome'] + keywords=['pony', 'ponies', 'awesome'], + meta_extras = { + 'viewport': 'width=device-width, initial-scale=1.0, minimum-scale=1.0' + } + 'extra_custom_props': [ + ('http-equiv', 'Content-Type', 'text/html; charset=UTF-8'), + ] ) When the time comes to render the template, simply include the instance as diff --git a/meta/templates/meta.html b/meta/templates/meta.html index 949d5f1..68b6ec9 100644 --- a/meta/templates/meta.html +++ b/meta/templates/meta.html @@ -3,6 +3,8 @@ {% if meta %} {% if meta.description %}{% meta 'description' meta.description %}{% endif %} {% if meta.keywords %}{% meta_list 'keywords' meta.keywords %}{% endif %} +{% if meta.extra_props %}{% meta_extras meta.extra_props %}{% endif %} +{% if meta.extra_custom_props %}{% custom_meta_extras meta.extra_custom_props %}{% endif %} {% if meta.use_og %} {% if meta.title %}{% og_prop 'title' meta.title %}{% endif %} {% if meta.url %}{% og_prop 'url' meta.url %}{% endif %} @@ -10,12 +12,14 @@ {% if meta.image %}{% og_prop 'image' meta.image %}{% endif %} {% if meta.object_type %}{% og_prop 'type' meta.object_type %}{% endif %} {% if meta.site_name %}{% og_prop 'site_name' meta.site_name %}{% endif %} +{% if meta.locale %}{% og_prop 'locale' meta.locale%}{% endif %} {% endif %} {% if meta.use_twitter %} {% if meta.title %}{% twitter_prop 'title' meta.title %}{% endif %} {% if meta.url %}{% twitter_prop 'url' meta.url %}{% endif %} {% if meta.description %}{% twitter_prop 'description' meta.description %}{% endif %} {% if meta.image %}{% twitter_prop 'image' meta.image %}{% endif %} +{% if meta.twitter_site %}{% twitter_prop 'site' meta.twitter_site %}{% endif %} {% endif %} {% if meta.use_googleplus %} {% if meta.title %}{% googleplus_prop 'name' meta.title %}{% endif %} diff --git a/meta/templatetags/meta.py b/meta/templatetags/meta.py index 85f6233..1172c18 100644 --- a/meta/templatetags/meta.py +++ b/meta/templatetags/meta.py @@ -41,6 +41,9 @@ def googleplus_html_scope(value): def meta(name, value): return '' % (name, value) +@register.simple_tag +def custom_meta(name_key, name_value, content): + return '' % (name_key, name_value, content) @register.simple_tag def meta_list(name, lst): @@ -48,3 +51,13 @@ def meta_list(name, lst): return '' % (name, ', '.join(lst)) except: return '' + +@register.simple_tag +def meta_extras(extra_props): + return ' '.join([meta(name, extra_props[name]) if extra_props[name] else '' + for name in extra_props]) + +@register.simple_tag +def custom_meta_extras(extra_custom_props): + return ' '.join([custom_meta(name_key, name_value, content) if content else '' + for name_key, name_value, content in extra_custom_props]) diff --git a/meta/views.py b/meta/views.py index a1d0d4b..815d4ef 100644 --- a/meta/views.py +++ b/meta/views.py @@ -16,11 +16,15 @@ def __init__(self, **kwargs): self.use_sites = kwargs.get('use_sites', settings.USE_SITES) self.title = kwargs.get('title') self.description = kwargs.get('description') + self.extra_props = kwargs.get('extra_props') + self.extra_custom_props = kwargs.get('extra_custom_props') self.keywords = kwargs.get('keywords') self.url = kwargs.get('url') self.image = kwargs.get('image') self.object_type = kwargs.get('object_type', settings.SITE_TYPE) self.site_name = kwargs.get('site_name', settings.SITE_NAME) + self.twitter_site = kwargs.get('twitter_site') + self.locale = kwargs.get('locale') self.use_og = kwargs.get('use_og', settings.USE_OG_PROPERTIES) self.use_twitter = kwargs.get('use_twitter', settings.USE_TWITTER_PROPERTIES) self.use_googleplus = kwargs.get('use_googleplus', settings.USE_GOOGLEPLUS_PROPERTIES) @@ -102,11 +106,15 @@ class MetadataMixin(object): meta_class = Meta title = None description = None + extra_props = None + extra_custom_props = None keywords = [] url = None image = None object_type = None site_name = None + twitter_site = None + locale = None use_sites = settings.USE_SITES use_og = settings.USE_OG_PROPERTIES @@ -140,6 +148,18 @@ def get_meta_object_type(self, context={}): def get_meta_site_name(self, context={}): return self.site_name or settings.SITE_NAME + def get_meta_extra_props(self, context={}): + return self.extra_props + + def get_meta_extra_custom_props(self, context={}): + return self.extra_custom_props + + def get_meta_twitter_site(self, context={}): + return self.twitter_site + + def get_meta_locale(self, context={}): + return self.locale + def get_context_data(self, **kwargs): context = super(MetadataMixin, self).get_context_data(**kwargs) context['meta'] = self.get_meta_class()( @@ -147,10 +167,14 @@ def get_context_data(self, **kwargs): use_sites=self.use_sites, title=self.get_meta_title(context=context), description=self.get_meta_description(context=context), + extra_props=self.get_meta_extra_props(context=context), + extra_custom_props=self.get_meta_extra_custom_props(context=context), keywords=self.get_meta_keywords(context=context), image=self.get_meta_image(context=context), url=self.get_meta_url(context=context), object_type=self.get_meta_object_type(context=context), site_name=self.get_meta_site_name(context=context), + twitter_site=self.get_meta_twitter_site(context=context), + locale=self.get_meta_locale(context=context), ) return context diff --git a/tests/test_meta.py b/tests/test_meta.py index cf2aabd..907e4e6 100644 --- a/tests/test_meta.py +++ b/tests/test_meta.py @@ -27,11 +27,15 @@ def test_defaults(self): m = Meta() self.assertEqual(m.title, None) self.assertEqual(m.description, None) + self.assertEqual(m.extra_props, None) + self.assertEqual(m.extra_custom_props, None) self.assertEqual(m.keywords, []) self.assertEqual(m.url, None) self.assertEqual(m.image, None) self.assertEqual(m.object_type, None) self.assertEqual(m.site_name, None) + self.assertEqual(m.twitter_site, None) + self.assertEqual(m.locale, None) self.assertEqual(m.use_og, False) self.assertEqual(m.use_sites, False) diff --git a/tests/test_metadata_mixin.py b/tests/test_metadata_mixin.py index 53ee4b9..583d867 100644 --- a/tests/test_metadata_mixin.py +++ b/tests/test_metadata_mixin.py @@ -116,6 +116,70 @@ def test_get_meta_site_name_with_setting(self): 'Foo' ) + def test_get_meta_extra_props(self): + m = MetadataMixin() + self.assertEqual( + m.get_meta_extra_props(), + None + ) + + m.extra_props = { + 'app_name': 'Foo', + 'app_id': 'Bar' + } + self.assertEqual( + m.get_meta_extra_props(), + { + 'app_name': 'Foo', + 'app_id': 'Bar' + } + ) + + def test_get_meta_extra_custom_props(self): + m = MetadataMixin() + self.assertEqual( + m.get_meta_extra_custom_props(), + None + ) + + m.extra_props = [ + ('property', 'app_name', 'Foo'), + ('property', 'app_id', 'Bar'), + ] + self.assertEqual( + m.get_meta_extra_props(), + [ + ('property', 'app_name', 'Foo'), + ('property', 'app_id', 'Bar'), + ] + ) + + def test_get_meta_twitter_site(self): + m = MetadataMixin() + self.assertEqual( + m.get_meta_twitter_site(), + None + ) + + m.twitter_site = '@foo' + self.assertEqual( + m.get_meta_twitter_site(), + '@foo' + ) + + def test_get_meta_locale(self): + m = MetadataMixin() + self.assertEqual( + m.get_meta_locale(), + None + ) + + m.locale = 'en_US' + self.assertEqual( + m.get_meta_locale(), + 'en_US' + ) + def test_get_context(self): class Super(object): def get_context_data(self): diff --git a/tests/test_templatetags.py b/tests/test_templatetags.py index 35ded5b..348050f 100644 --- a/tests/test_templatetags.py +++ b/tests/test_templatetags.py @@ -7,7 +7,7 @@ from meta.templatetags.meta import ( og_prop, meta, meta_list, twitter_prop, generic_prop, - googleplus_prop, googleplus_html_scope) + googleplus_prop, googleplus_html_scope, custom_meta, custom_meta_extras, meta_extras) class OgPropTestCase(unittest.TestCase): @@ -31,6 +31,14 @@ def test_meta_basically_works(self): ) +class CustomMetaTestCase(unittest.TestCase): + def test_custom_meta_basically_works(self): + self.assertEqual( + custom_meta('property', 'foo', 'bar'), + '' + ) + + class TwitterPropTestCase(unittest.TestCase): def test_twitter_basically_works(self): self.assertEqual( @@ -65,3 +73,23 @@ def test_meta_list_with_non_list_value(self): meta_list('keywords', 12), '' ) + + +class MetaExtrasTestCase(unittest.TestCase): + def test_meta_extras_basically_works(self): + result = meta_extras({ + 'type': 'foo', + 'image_width': 'bar' + }) + self.assertTrue('' in result) + self.assertTrue('' in result) + + +class CustomMetaExtrasTestCase(unittest.TestCase): + def test_custom_meta_extras_basically_works(self): + result = custom_meta_extras([ + ('property', 'type', 'foo'), + ('key', 'image_width', 'bar') + ]) + self.assertTrue('' in result) + self.assertTrue('' in result)