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

rafalp / Misago / 15760070102

19 Jun 2025 02:18PM UTC coverage: 97.286% (+0.07%) from 97.214%
15760070102

Pull #1944

github

web-flow
Merge 1e99a089b into 7565eefd3
Pull Request #1944: Replace thread events with updates

2828 of 2914 new or added lines in 89 files covered. (97.05%)

13 existing lines in 4 files now uncovered.

74124 of 76192 relevant lines covered (97.29%)

0.97 hits per line

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

67.74
/misago/threads/viewmodels/posts.py
1
from ...acl.objectacl import add_acl_to_obj
1✔
2
from ...core.shortcuts import paginate, pagination_dict
1✔
3
from ...users.online.utils import make_users_status_aware
1✔
4
from ..paginator import PostsPaginator
1✔
5
from ..permissions import exclude_invisible_posts
1✔
6
from ..serializers import PostSerializer
1✔
7
from ..utils import add_likes_to_posts
1✔
8

9
__all__ = ["ThreadPosts"]
1✔
10

11

12
class ViewModel:
1✔
13
    def __init__(self, request, thread, page):  # pylint: disable=too-many-locals
1✔
14
        try:
1✔
15
            thread_model = thread.unwrap()
1✔
16
        except AttributeError:
×
17
            thread_model = thread
×
18

19
        posts_queryset = self.get_posts_queryset(request, thread_model)
1✔
20

21
        posts_limit = request.settings.posts_per_page
1✔
22
        posts_orphans = request.settings.posts_per_page_orphans
1✔
23
        list_page = paginate(
1✔
24
            posts_queryset, page, posts_limit, posts_orphans, paginator=PostsPaginator
25
        )
26
        paginator = pagination_dict(list_page)
1✔
27

28
        posts = list(list_page.object_list)
1✔
29
        posters = []
1✔
30

31
        for post in posts:
1✔
32
            post.category = thread.category
1✔
33
            post.thread = thread_model
1✔
34

35
            if post.poster:
1✔
36
                posters.append(post.poster)
×
37

38
        make_users_status_aware(request, posters)
1✔
39

40
        if thread.category.acl["can_see_posts_likes"]:
1✔
41
            add_likes_to_posts(request.user, posts)
1✔
42

43
        # add events to posts
44
        if thread_model.has_events:
1✔
45
            first_post = None
×
46
            if list_page.has_previous():
×
47
                first_post = posts[0]
×
48
            last_post = None
×
49
            if list_page.has_next():
×
50
                last_post = posts[-1]
×
51

NEW
52
            events_limit = 20
×
53
            posts += self.get_events_queryset(
×
54
                request, thread_model, events_limit, first_post, last_post
55
            )
56

57
            # sort both by pk
58
            posts.sort(key=lambda p: p.pk)
×
59

60
        # make posts and events ACL aware
61
        add_acl_to_obj(request.user_acl, posts)
1✔
62

63
        self._user = request.user
1✔
64

65
        self.posts = posts
1✔
66
        self.paginator = paginator
1✔
67

68
    def get_posts_queryset(self, request, thread):
1✔
69
        queryset = (
1✔
70
            thread.post_set.select_related(
71
                "category",
72
                "poster",
73
                "poster__rank",
74
                "poster__ban_cache",
75
                "poster__online_tracker",
76
            )
77
            .filter(is_event=False)
78
            .order_by("id")
79
        )
80
        return exclude_invisible_posts(request.user_acl, thread.category, queryset)
1✔
81

82
    def get_events_queryset(
1✔
83
        self, request, thread, limit, first_post=None, last_post=None
84
    ):
85
        queryset = thread.post_set.select_related(
×
86
            "category",
87
            "poster",
88
            "poster__rank",
89
            "poster__ban_cache",
90
            "poster__online_tracker",
91
        ).filter(is_event=True)
92

93
        if first_post:
×
94
            queryset = queryset.filter(pk__gt=first_post.pk)
×
95
        if last_post:
×
96
            queryset = queryset.filter(pk__lt=last_post.pk)
×
97

98
        queryset = exclude_invisible_posts(request.user_acl, thread.category, queryset)
×
99
        return list(queryset.order_by("-id")[:limit])
×
100

101
    def get_frontend_context(self):
1✔
102
        context = {
1✔
103
            "results": PostSerializer(
104
                self.posts, many=True, context={"user": self._user}
105
            ).data
106
        }
107

108
        context.update(self.paginator)
1✔
109

110
        return context
1✔
111

112
    def get_template_context(self):
1✔
113
        return {"posts": self.posts, "paginator": self.paginator}
×
114

115

116
class ThreadPosts(ViewModel):
1✔
117
    pass
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc