Completed
Push — master ( 01ef11...4b15c2 )
by
unknown
8s
created

GFKQuerySet._clone()   B

Complexity

Conditions 5

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
dl 0
loc 12
rs 8.5454
c 0
b 0
f 0
1
from django.db.models import Manager
2
from django.db.models.query import QuerySet, EmptyQuerySet
3
from django import VERSION as DJANGO_VERSION
4
try:
5
    from django.contrib.contenttypes.fields import GenericForeignKey
6
except ImportError:
7
    from django.contrib.contenttypes.generic import GenericForeignKey
8
9
from actstream import settings
10
11
12
class GFKManager(Manager):
13
    """
14
    A manager that returns a GFKQuerySet instead of a regular QuerySet.
15
16
    """
17
    def get_query_set(self):
18
        return GFKQuerySet(self.model)
19
    get_queryset = get_query_set
20
21
    def none(self):
22
        return self.get_queryset().none()
23
24
25
class GFKQuerySet(QuerySet):
26
    """
27
    A QuerySet with a fetch_generic_relations() method to bulk fetch
28
    all generic related items.  Similar to select_related(), but for
29
    generic foreign keys. This wraps QuerySet.prefetch_related.
30
    """
31
    def fetch_generic_relations(self, *args):
32
        qs = self._clone()
33
34
        if not settings.FETCH_RELATIONS:
35
            return qs
36
37
        # Backward compatibility patch for
38
        # Django versions lower than 1.11.x
39
        if DJANGO_VERSION >= (1, 11):
40
            private_fields = self.model._meta.private_fields
41
        else:
42
            private_fields = self.model._meta.virtual_fields
43
44
        gfk_fields = [g for g in private_fields if isinstance(g, GenericForeignKey)]
45
46
        if args:
47
            gfk_fields = [g for g in gfk_fields if g.name in args]
48
49
        return qs.prefetch_related(*[g.name for g in gfk_fields])
50
51
    def _clone(self, klass=None,  **kwargs):
52
        if DJANGO_VERSION >= (2, 0):
53
            return super(GFKQuerySet, self)._clone()
54
55
        for name in ['subclasses', '_annotated']:
56
            if hasattr(self, name):
57
                kwargs[name] = getattr(self, name)
58
59
        if DJANGO_VERSION < (1, 9):
60
            kwargs['klass'] = klass
61
62
        return super(GFKQuerySet, self)._clone(**kwargs)
63
64
    def none(self):
65
        clone = self._clone({'klass': EmptyGFKQuerySet})
66
        if hasattr(clone.query, 'set_empty'):
67
            clone.query.set_empty()
68
        return clone
69
70
71
class EmptyGFKQuerySet(GFKQuerySet, EmptyQuerySet):
72
    def fetch_generic_relations(self, *args):
73
        return self
74