Passed
Push — master ( 2e9b83...b9a4d3 )
by Swen
01:53
created

LocalizedUniqueSlugField.pre_save()   D

Complexity

Conditions 10

Size

Total Lines 59

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 24
CRAP Score 10.0064

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 10
c 2
b 0
f 0
dl 0
loc 59
ccs 24
cts 25
cp 0.96
crap 10.0064
rs 4.8648

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like LocalizedUniqueSlugField.pre_save() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1 1
from datetime import datetime
2
3 1
from django.conf import settings
4 1
from django.utils.text import slugify
5 1
from django.core.exceptions import ImproperlyConfigured
6
7 1
from ..util import get_language_codes
8 1
from ..mixins import AtomicSlugRetryMixin
9 1
from ..localized_value import LocalizedValue
10 1
from .localized_autoslug_field import LocalizedAutoSlugField
11
12
13 1
class LocalizedUniqueSlugField(LocalizedAutoSlugField):
14
    """Automatically provides slugs for a localized
15
    field upon saving."
16
17
    An improved version of :see:LocalizedAutoSlugField,
18
    which adds:
19
20
        - Concurrency safety
21
        - Improved performance
22
23
    When in doubt, use this over :see:LocalizedAutoSlugField.
24
    Inherit from :see:AtomicSlugRetryMixin in your model to
25
    make this field work properly.
26
    """
27
28 1
    def __init__(self, *args, **kwargs):
29
        """Initializes a new instance of :see:LocalizedUniqueSlugField."""
30
31 1
        kwargs['uniqueness'] = kwargs.pop('uniqueness', get_language_codes())
32
33 1
        super(LocalizedUniqueSlugField, self).__init__(
34
            *args,
35
            **kwargs
36
        )
37
38 1
        self.populate_from = kwargs.pop('populate_from')
39 1
        self.include_time = kwargs.pop('include_time', False)
40
41 1
    def deconstruct(self):
42
        """Deconstructs the field into something the database
43
        can store."""
44
45 1
        name, path, args, kwargs = super(
46
            LocalizedUniqueSlugField, self).deconstruct()
47
48 1
        kwargs['populate_from'] = self.populate_from
49 1
        kwargs['include_time'] = self.include_time
50 1
        return name, path, args, kwargs
51
52 1
    def pre_save(self, instance, add: bool):
53
        """Ran just before the model is saved, allows us to built
54
        the slug.
55
56
        Arguments:
57
            instance:
58
                The model that is being saved.
59
60
            add:
61
                Indicates whether this is a new entry
62
                to the database or an update.
63
64
        Returns:
65
            The localized slug that was generated.
66
        """
67
68 1
        if not isinstance(instance, AtomicSlugRetryMixin):
69
            raise ImproperlyConfigured((
70
                'Model \'%s\' does not inherit from AtomicSlugRetryMixin. '
71
                'Without this, the LocalizedUniqueSlugField will not work.'
72
            ) % type(instance).__name__)
73
74 1
        slugs = LocalizedValue()
75
76 1
        for lang_code, _ in settings.LANGUAGES:
77 1
            value = self._get_populate_from_value(
78
                instance,
79
                self.populate_from,
80
                lang_code
81
            )
82
83 1
            if not value:
84 1
                continue
85
86 1
            slug = slugify(value, allow_unicode=True)
87
88
            # verify whether it's needed to re-generate a slug,
89
            # if not, re-use the same slug
90 1
            if instance.pk is not None:
91 1
                current_slug = getattr(instance, self.name).get(lang_code)
92 1
                if current_slug is not None:
93 1
                    stripped_slug = current_slug[0:current_slug.rfind('-')]
94 1
                    if slug == stripped_slug:
95 1
                        slugs.set(lang_code, current_slug)
96 1
                        continue
97
98 1
            if self.include_time:
99 1
                slug += '-%d' % datetime.now().microsecond
100
101 1
            if instance.retries > 0:
102
                # do not add another - if we already added time
103 1
                if not self.include_time:
104 1
                    slug += '-'
105 1
                slug += '%d' % instance.retries
106
107 1
            slugs.set(lang_code, slug)
108
109 1
        setattr(instance, self.name, slugs)
110
        return slugs
111