thread.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. from django.urls import reverse
  2. from rest_framework import serializers
  3. from misago.categories.serializers import CategorySerializer
  4. from misago.core.serializers import MutableFields
  5. from misago.threads.models import Thread
  6. from .poll import PollSerializer
  7. from .threadparticipant import ThreadParticipantSerializer
  8. __all__ = ["ThreadSerializer", "PrivateThreadSerializer", "ThreadsListSerializer"]
  9. BasicCategorySerializer = CategorySerializer.subset_fields(
  10. "id",
  11. "parent",
  12. "name",
  13. "description",
  14. "is_closed",
  15. "css_class",
  16. "level",
  17. "lft",
  18. "rght",
  19. "is_read",
  20. "url",
  21. )
  22. class ThreadSerializer(serializers.ModelSerializer, MutableFields):
  23. category = BasicCategorySerializer(many=False, read_only=True)
  24. acl = serializers.SerializerMethodField()
  25. has_unapproved_posts = serializers.SerializerMethodField()
  26. is_new = serializers.SerializerMethodField()
  27. is_read = serializers.SerializerMethodField()
  28. path = BasicCategorySerializer(many=True, read_only=True)
  29. poll = PollSerializer(many=False, read_only=True)
  30. best_answer = serializers.PrimaryKeyRelatedField(read_only=True)
  31. best_answer_marked_by = serializers.PrimaryKeyRelatedField(read_only=True)
  32. subscription = serializers.SerializerMethodField()
  33. api = serializers.SerializerMethodField()
  34. url = serializers.SerializerMethodField()
  35. class Meta:
  36. model = Thread
  37. fields = [
  38. "id",
  39. "category",
  40. "title",
  41. "replies",
  42. "has_unapproved_posts",
  43. "started_on",
  44. "starter_name",
  45. "last_post_on",
  46. "last_post_is_event",
  47. "last_post",
  48. "last_poster_name",
  49. "is_unapproved",
  50. "is_hidden",
  51. "is_closed",
  52. "weight",
  53. "best_answer",
  54. "best_answer_is_protected",
  55. "best_answer_marked_on",
  56. "best_answer_marked_by",
  57. "best_answer_marked_by_name",
  58. "best_answer_marked_by_slug",
  59. "acl",
  60. "is_new",
  61. "is_read",
  62. "path",
  63. "poll",
  64. "subscription",
  65. "api",
  66. "url",
  67. ]
  68. def get_acl(self, obj):
  69. try:
  70. return obj.acl
  71. except AttributeError:
  72. return {}
  73. def get_has_unapproved_posts(self, obj):
  74. try:
  75. acl = obj.acl
  76. except AttributeError:
  77. return False
  78. return acl.get("can_approve") and obj.has_unapproved_posts
  79. def get_is_new(self, obj):
  80. try:
  81. return obj.is_new
  82. except AttributeError:
  83. return None
  84. def get_is_read(self, obj):
  85. try:
  86. return obj.is_read
  87. except AttributeError:
  88. return None
  89. def get_participants(self, obj):
  90. return ThreadParticipantSerializer(obj.participants_list, many=True).data
  91. def get_subscription(self, obj):
  92. try:
  93. return obj.subscription.send_email
  94. except AttributeError:
  95. return None
  96. def get_api(self, obj):
  97. return {
  98. "index": obj.get_api_url(),
  99. "editor": obj.get_editor_api_url(),
  100. "merge": obj.get_merge_api_url(),
  101. "poll": obj.get_poll_api_url(),
  102. "posts": {
  103. "index": obj.get_posts_api_url(),
  104. "merge": obj.get_post_merge_api_url(),
  105. "move": obj.get_post_move_api_url(),
  106. "split": obj.get_post_split_api_url(),
  107. },
  108. }
  109. def get_url(self, obj):
  110. return {
  111. "index": obj.get_absolute_url(),
  112. "new_post": obj.get_new_post_url(),
  113. "last_post": obj.get_last_post_url(),
  114. "best_answer": obj.get_best_answer_url(),
  115. "unapproved_post": obj.get_unapproved_post_url(),
  116. "starter": self.get_starter_url(obj),
  117. "last_poster": self.get_last_poster_url(obj),
  118. }
  119. def get_starter_url(self, obj):
  120. if obj.starter_id:
  121. return reverse(
  122. "misago:user", kwargs={"slug": obj.starter_slug, "pk": obj.starter_id}
  123. )
  124. return None
  125. def get_last_poster_url(self, obj):
  126. if obj.last_poster_id:
  127. return reverse(
  128. "misago:user",
  129. kwargs={"slug": obj.last_poster_slug, "pk": obj.last_poster_id},
  130. )
  131. return None
  132. class PrivateThreadSerializer(ThreadSerializer):
  133. participants = serializers.SerializerMethodField()
  134. class Meta:
  135. model = Thread
  136. fields = ThreadSerializer.Meta.fields + ["participants"]
  137. class ThreadsListSerializer(ThreadSerializer):
  138. category = serializers.PrimaryKeyRelatedField(read_only=True)
  139. last_post = serializers.PrimaryKeyRelatedField(read_only=True)
  140. starter = serializers.SerializerMethodField()
  141. last_poster = serializers.SerializerMethodField()
  142. class Meta:
  143. model = Thread
  144. fields = ThreadSerializer.Meta.fields + ["has_poll", "starter", "last_poster"]
  145. def get_starter(self, obj):
  146. if obj.starter_id:
  147. return {
  148. "id": obj.starter_id,
  149. "username": obj.starter.username,
  150. "real_name": obj.starter.get_real_name(),
  151. "avatars": obj.starter.avatars,
  152. }
  153. return None
  154. def get_last_poster(self, obj):
  155. if obj.last_poster_id:
  156. return {
  157. "id": obj.last_poster_id,
  158. "username": obj.last_poster.username,
  159. "real_name": obj.last_poster.get_real_name(),
  160. "avatars": obj.last_poster.avatars,
  161. }
  162. return None
  163. ThreadsListSerializer = ThreadsListSerializer.exclude_fields("path", "poll")