• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

akvo / akvo-mis / #763

28 Jul 2026 02:11PM UTC coverage: 88.756% (+0.2%) from 88.577%
#763

Pull #281

coveralls-python

zuhdil
[#270] Trim the read-filtering diff

Complexity-only pass; no behaviour changes.

- TenantManager was hand-written delegation of a single queryset method.
  models.Manager.from_queryset does exactly that, so the class collapses
  to one line. The soft-deletes and draft managers keep their explicit
  delegators: their get_queryset carries with_deleted/only_draft state
  that a generated manager would drop.

- The two-tenant fixture was copy-pasted across four isolation test
  modules, differing only in a trailing datapoint or assignment. It
  moves to a TenantIsolationTestCase base that each app extends by
  overriding make_tenant.

- fetchLevels expressed "use the array or an empty one" through two
  separate store writes. A two-argument then collapses both paths into
  one update; the rejection path is kept because it clears the previous
  tenant's levels on a refetch.
Pull Request #281: [#270] Filter every read by tenant

5714 of 6609 branches covered (86.46%)

Branch coverage included in aggregate %.

10862 of 12067 relevant lines covered (90.01%)

0.9 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.87
backend/utils/draft_model.py
1
from django.db import models
1✔
2
from .soft_deletes_model import SoftDeletesQuerySet, SoftDeletesManager
1✔
3
from .tenant_scoped_model import TenantScopedQuerySetMixin
1✔
4

5

6
class DraftQuerySet(TenantScopedQuerySetMixin, models.QuerySet):
1✔
7
    def only_draft(self):
1✔
8
        return self.filter(is_draft=True)
×
9

10
    def without_draft(self):
1✔
11
        return self.filter(is_draft=False)
×
12

13
    def published(self):
1✔
14
        return self.filter(is_draft=False)
×
15

16

17
class DraftSoftDeletesQuerySet(SoftDeletesQuerySet):
1✔
18
    def only_draft(self):
1✔
19
        return self.filter(is_draft=True)
1✔
20

21
    def without_draft(self):
1✔
22
        return self.filter(is_draft=False)
×
23

24
    def published(self):
1✔
25
        return self.filter(is_draft=False)
×
26

27

28
class DraftManager(models.Manager):
1✔
29
    def __init__(self, *args, **kwargs):
1✔
30
        self.only_draft = kwargs.pop("only_draft", False)
1✔
31
        super().__init__(*args, **kwargs)
1✔
32

33
    def get_queryset(self):
1✔
34
        if self.only_draft:
×
35
            return DraftQuerySet(self.model).only_draft()
×
36
        return DraftQuerySet(self.model).without_draft()
×
37

38
    def published(self):
1✔
39
        return self.get_queryset().published()
×
40

41
    def draft(self):
1✔
42
        return DraftQuerySet(self.model).only_draft()
×
43

44
    def for_user(self, user):
1✔
45
        return self.get_queryset().for_user(user)
×
46

47

48
class DraftSoftDeletesManager(SoftDeletesManager):
1✔
49
    def __init__(self, *args, **kwargs):
1✔
50
        self.only_draft = kwargs.pop("only_draft", False)
1✔
51
        super().__init__(*args, **kwargs)
1✔
52

53
    def get_queryset(self):
1✔
54
        if self.only_draft:
1✔
55
            # For draft data, we only care about non-deleted drafts
56
            # since drafts are always hard deleted
57
            queryset = DraftSoftDeletesQuerySet(self.model)
1✔
58
            return queryset.without_deleted().only_draft()
1✔
59
        # For non-draft queries, use the parent logic
60
        return super().get_queryset()
1✔
61

62
    def draft(self):
1✔
63
        queryset = DraftSoftDeletesQuerySet(self.model)
×
64
        return queryset.without_deleted().only_draft()
×
65

66

67
class Draft(models.Model):
1✔
68
    is_draft = models.BooleanField(default=False)
1✔
69

70
    class Meta:
1✔
71
        abstract = True
1✔
72

73
    objects = DraftManager()
1✔
74
    objects_draft = DraftManager(only_draft=True)
1✔
75

76
    def publish(self) -> None:
1✔
77
        self.is_draft = False
1✔
78
        self.save(update_fields=["is_draft"])
1✔
79

80
    def mark_as_draft(self) -> None:
1✔
81
        self.is_draft = True
1✔
82
        self.save(update_fields=["is_draft"])
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc