Skip to content
Snippets Groups Projects
utils.py 9.5 KiB
Newer Older
Olivier Le Brouster's avatar
Olivier Le Brouster committed
# -*- coding: utf-8 -*-
Dylann Cordel's avatar
Dylann Cordel committed

from __future__ import unicode_literals, print_function
Dylann Cordel's avatar
Dylann Cordel committed

try:
    from django.apps import apps
    get_model = apps.get_model
except:
    from django.db.models.loading import get_model
Olivier Le Brouster's avatar
Olivier Le Brouster committed

try:
    from cms.models.placeholdermodel import Placeholder
    from cms.api import add_plugin
except ImportError:
    with_cms = False
else:
    with_cms = True
Dylann Cordel's avatar
Dylann Cordel committed

# array of available NewsTypes
# for each NewsType, we define a subarray with the model to use and
# default fields values in "overwrites" which is a subarray too :
#   - inherit is a list of other NewsTypes to get default fields.from their conf
#   - key 0 is the default values for all news
#   - keys 1 to N is an array with values to overwrite for news 1 to N.
# Can also contain a "languages" list with language code for translations.
# Only used for I18N Models. Translations are in "translations" variable.
newsTypes = {
    'myapp.News': {
        'overwrites': {
            'inherit': [],
            # 0 is for base values
            0: {
                'newsbox_slug': 'news-%(i)d',
                'newsbox_title': 'News %(i)d',
                'newsbox_date': None,
                'newsbox_publication_start_date': '2014-03-%(i)02dT10:00:00+02:00',
                'newsbox_published': True,
                'newsbox_summary': 'Summary of the news %(i)d',
                'newsbox_body': 'Body of the news %(i)d',
Olivier Le Brouster's avatar
Olivier Le Brouster committed
            },
            1: {},
            2: {'newsbox_published': False},
            3: {'newsbox_publication_start_date': '2020-01-01T10:00:00+02:00'},
            4: {'newsbox_body': ''},
            5: {'newsbox_published': False},
            6: {'newsbox_date': '2028-01-01T10:00:00+02:00',
                'newsbox_publication_start_date': '2005-07-15T10:00:00+02:00'},
            7: {'newsbox_date': '1985-07-02T10:00:00+02:00'},
Olivier Le Brouster's avatar
Olivier Le Brouster committed
        },
    },
    'myapp.NewsExpired': {
        'overwrites': {
            'inherit': ['myapp.News', ],
            5: {
                'newsbox_published': True,
                'newsbox_publication_end_date': '2014-06-01T10:00:00+02:00',
Olivier Le Brouster's avatar
Olivier Le Brouster committed
            },
        },
    },
    'myapp.NewsSEO': {
        'overwrites': {
            'inherit': ['myapp.News', ],
            0: {
                'newsbox_indexed': True,
                'newsbox_meta_description': 'Meta description of the news %(i)d',
                'newsbox_meta_keywords': 'keyword1, keyword2, news-%(i)d',
Olivier Le Brouster's avatar
Olivier Le Brouster committed
            },
            6: {
                'newsbox_indexed': False,
Olivier Le Brouster's avatar
Olivier Le Brouster committed
            },
        },
    },
    'myapp.NewsComplete': {
        'overwrites': {
            'inherit': ['myapp.NewsExpired', 'myapp.NewsSEO'],
Olivier Le Brouster's avatar
Olivier Le Brouster committed
        },
    },
    'myapp.NewsExtended': {
        'overwrites': {
            'inherit': ['myapp.NewsComplete'],
            0: {
                'general_field': 'Test',
                'content_field': 'Extra content of the news %(i)d',
                'seo_field': 'Extra SEO of the news %(i)d',
Olivier Le Brouster's avatar
Olivier Le Brouster committed
            },
        }
    },

    # I18N Models
    'myapp_i18n.News': {
        'languages': ['en', 'fr', ],
        'overwrites': {
            'inherit': ['myapp.News', ],
Olivier Le Brouster's avatar
Olivier Le Brouster committed
        },
    },
    'myapp_i18n.NewsComplete': {
        'languages': ['en', 'fr', ],
        'overwrites': {
            'inherit': ['myapp.NewsComplete', 'myapp_i18n.News'],
Olivier Le Brouster's avatar
Olivier Le Brouster committed
        },
    },
    'myapp_i18n.NewsExtended': {
        'languages': ['en', 'fr', ],
        'overwrites': {
            'inherit': ['myapp.NewsExtended', 'myapp_i18n.NewsComplete'],
Olivier Le Brouster's avatar
Olivier Le Brouster committed
        },
    },
}
if with_cms:
    newsTypes.update({
        # CMS Models
        'myapp_cms.News': {
Dylann Cordel's avatar
Dylann Cordel committed
            'overwrites': {
                'inherit': ['myapp.News', ],
                0: {
                    'newsbox_summary': '<p>Summary of the news %(i)d</p>',
                    'newsbox_body': '<p>Body of the news %(i)d</p>',
                },
Olivier Le Brouster's avatar
Olivier Le Brouster committed
            },
        },
        'myapp_cms.NewsComplete': {
Dylann Cordel's avatar
Dylann Cordel committed
            'overwrites': {
                'inherit': ['myapp.NewsComplete', 'myapp_cms.News'],
Olivier Le Brouster's avatar
Olivier Le Brouster committed
            },
        },
        'myapp_cms.NewsExtended': {
Dylann Cordel's avatar
Dylann Cordel committed
            'overwrites': {
                'inherit': ['myapp_cms.NewsComplete'],
Olivier Le Brouster's avatar
Olivier Le Brouster committed
            },
        },
Dylann Cordel's avatar
Dylann Cordel committed
        # ALL Models
        'myapp_all.News': {
Dylann Cordel's avatar
Dylann Cordel committed
            'languages': ['en', 'fr', ],
            'overwrites': {
                'inherit': ['myapp.News', ],
Dylann Cordel's avatar
Dylann Cordel committed
                0: {
                    'newsbox_summary': '<p>Summary of the news %(i)d</p>',
                    'newsbox_body': '<p>Body of the news %(i)d</p>',
Olivier Le Brouster's avatar
Olivier Le Brouster committed
                },
            },
        },
        'myapp_all.NewsComplete': {
Dylann Cordel's avatar
Dylann Cordel committed
            'languages': ['en', 'fr', ],
            'overwrites': {
                'inherit': ['myapp.NewsComplete', 'myapp_all.News'],
Olivier Le Brouster's avatar
Olivier Le Brouster committed
            },
        },
        'myapp_all.NewsExtended': {
Dylann Cordel's avatar
Dylann Cordel committed
            'languages': ['en', 'fr', ],
            'overwrites': {
                'inherit': ['myapp.NewsExtended', 'myapp_all.NewsComplete'],
Olivier Le Brouster's avatar
Olivier Le Brouster committed
            },
        },
    })


def get_fields_values(newsTypes, newsType, i, inherited):
    fields_values = {}
    if newsType in inherited:
        return fields_values
    inherited.append(newsType)

    for inheritedType in newsTypes[newsType]['overwrites']['inherit']:
        fields_values.update(get_fields_values(newsTypes, inheritedType, i, []))
    if i in newsTypes[newsType]['overwrites']:
        fields_values.update(newsTypes[newsType]['overwrites'][i])
    return fields_values


def create_tests_data(app=None, verbosity=0):

    # Translations of translatable fields
    translations = {
        'en': {
            # default content is already in english
        },
        'fr': {
            'newsbox_slug': 'actualite-%(i)d',
            'newsbox_title': 'Actualité %(i)d',
            'newsbox_summary': 'Résumé de l\'actualité %(i)d',
            'newsbox_body': 'Corps de l\'actualité %(i)d',
            'newsbox_meta_description': 'Meta description de l\'actualité %(i)d',
            'newsbox_meta_keywords': 'motclef1, motclef2, actualite-%(i)d',
            'content_field': 'Contenu additionnel de l\'actualité %(i)d',
            'seo_field': 'SEO additionnel de l\'actualité %(i)d',
        },
Olivier Le Brouster's avatar
Olivier Le Brouster committed
    }
    translatable_fields = translations['fr'].keys()

    nb_news_a_creer = len(newsTypes['myapp.News']['overwrites'])-2
Olivier Le Brouster's avatar
Olivier Le Brouster committed
    for newsType, infos in newsTypes.items():
        app_label, model_name = newsType.split('.')
        if app and app != app_label:
Olivier Le Brouster's avatar
Olivier Le Brouster committed
            continue
        model = get_model(app_label, model_name)
        if with_cms:
            # Transform field into placeholders if needed
            ph_names = getattr(model._meta, 'placeholder_field_names')
Olivier Le Brouster's avatar
Olivier Le Brouster committed
        base_kwargs = get_fields_values(newsTypes, newsType, 0, [])

        if verbosity >= 2:
            print('\n%s\n' % newsType + '-' * len(newsType))
Olivier Le Brouster's avatar
Olivier Le Brouster committed
        for i in range(1, nb_news_a_creer+1):
Dylann Cordel's avatar
Dylann Cordel committed
            if 'languages' not in infos:
                infos['languages'] = [None, ]
Olivier Le Brouster's avatar
Olivier Le Brouster committed

            for lang in infos['languages']:
                kwargs = base_kwargs.copy()
                kwargs.update(get_fields_values(newsTypes, newsType, i, []))
Dylann Cordel's avatar
Dylann Cordel committed
                # Retrieve translated values if a lang is specified
Olivier Le Brouster's avatar
Olivier Le Brouster committed
                if lang and lang in translations and translations[lang]:
                    for k in translations[lang]:
Dylann Cordel's avatar
Dylann Cordel committed
                        if k in kwargs:
Olivier Le Brouster's avatar
Olivier Le Brouster committed
                            if kwargs[k][0:3] == '<p>':
                                kwargs[k] = '<p>'+translations[lang][k]+'</p>'
                            else:
                                kwargs[k] = translations[lang][k]

Dylann Cordel's avatar
Dylann Cordel committed
                # Add the "nth" informations for fields which need it
Olivier Le Brouster's avatar
Olivier Le Brouster committed
                for k in kwargs:
                    if isinstance(kwargs[k], type('')):
                        kwargs[k] = kwargs[k] % {'i': i}
                if with_cms and ph_names:
                    try:
                        for ph_name in ph_names:
                            if ph_name not in kwargs:
                                continue
                            ph = Placeholder.objects.create(slot=ph_name)
                            add_plugin(ph, 'TextPlugin', lang if lang is not None else 'en',
                                       body=kwargs[ph_name])
                            kwargs[ph_name] = ph
                    except AttributeError:
                        pass
Dylann Cordel's avatar
Dylann Cordel committed
                translatable_values = {k: v for k, v in kwargs.items()
                                       if k in translatable_fields}
Olivier Le Brouster's avatar
Olivier Le Brouster committed
                untranslatable_fields = list(set(kwargs) - set(translatable_fields))
Dylann Cordel's avatar
Dylann Cordel committed
                untranslatable_values = {k: v for k, v in kwargs.items()
                                         if k in untranslatable_fields}
                if verbosity >= 2:
                    langstr = ' (%s)' % lang if lang else ''
                    print(' - %d%s : %s' % (i, langstr, kwargs['newsbox_title']))
                if not lang or lang == infos['languages'][0]:
                    news = model(**untranslatable_values)
Dylann Cordel's avatar
Dylann Cordel committed
                if lang:
                    news.save()
                    news.create_translation(lang, **translatable_values)
                else:
                    for field, value in translatable_values.items():
                        setattr(news, field, value)
                    news.save()


def delete_tests_data(app=None, verbosity=0):
    for newsType, infos in newsTypes.items():
        app_label, model_name = newsType.split('.')
        if app and app != app_label:
            continue
        model = get_model(app_label, model_name)
        # delete one by one to be sure to call signals or save method
        for obj in model.objects.all():
            obj.delete()