Completed
Push — master ( 087442...a6d359 )
by
unknown
13s
created

GFKQuerySet._clone()   A

Complexity

Conditions 4

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
c 1
b 0
f 0
dl 0
loc 9
rs 9.2
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
        return super(GFKQuerySet, self)._clone(**kwargs)
60
61
    def none(self):
62
        clone = self._clone({'klass': EmptyGFKQuerySet})
63
        if hasattr(clone.query, 'set_empty'):
64
            clone.query.set_empty()
65
        return clone
66
67
68
class EmptyGFKQuerySet(GFKQuerySet, EmptyQuerySet):
69
    def fetch_generic_relations(self, *args):
70
        return self
71