serializers.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. from rest_framework import serializers
  2. from django.urls import reverse
  3. from misago.core.serializers import MutableFields
  4. from misago.core.utils import format_plaintext_for_html
  5. from .models import Category
  6. __all__ = ['CategorySerializer']
  7. def last_activity_detail(f):
  8. """util for serializing last activity details"""
  9. def decorator(self, obj):
  10. if not obj.last_thread_id:
  11. return None
  12. acl = self.get_acl(obj)
  13. tested_acls = (acl.get('can_see'), acl.get('can_browse'), acl.get('can_see_all_threads'), )
  14. if not all(tested_acls):
  15. return None
  16. return f(self, obj)
  17. return decorator
  18. class CategorySerializer(serializers.ModelSerializer, MutableFields):
  19. parent = serializers.PrimaryKeyRelatedField(read_only=True)
  20. description = serializers.SerializerMethodField()
  21. is_read = serializers.SerializerMethodField()
  22. subcategories = serializers.SerializerMethodField()
  23. acl = serializers.SerializerMethodField()
  24. url = serializers.SerializerMethodField()
  25. class Meta:
  26. model = Category
  27. fields = [
  28. 'id',
  29. 'parent',
  30. 'name',
  31. 'description',
  32. 'is_closed',
  33. 'threads',
  34. 'posts',
  35. 'last_post_on',
  36. 'last_thread_title',
  37. 'last_poster',
  38. 'last_poster_name',
  39. 'css_class',
  40. 'is_read',
  41. 'subcategories',
  42. 'acl',
  43. 'level',
  44. 'lft',
  45. 'rght',
  46. 'url',
  47. ]
  48. def get_description(self, obj):
  49. if obj.description:
  50. return {
  51. 'plain': obj.description,
  52. 'html': format_plaintext_for_html(obj.description),
  53. }
  54. return None
  55. def get_is_read(self, obj):
  56. try:
  57. return obj.is_read
  58. except AttributeError:
  59. return None
  60. def get_subcategories(self, obj):
  61. try:
  62. return CategorySerializer(obj.subcategories, many=True).data
  63. except AttributeError:
  64. return []
  65. def get_acl(self, obj):
  66. try:
  67. return obj.acl
  68. except AttributeError:
  69. return {}
  70. @last_activity_detail
  71. def get_last_poster(self, obj):
  72. if obj.last_poster_id:
  73. return {
  74. 'id': obj.last_poster_id,
  75. 'avatars': obj.last_poster.avatars,
  76. 'url': reverse(
  77. 'misago:user', kwargs={
  78. 'slug': obj.last_poster_slug,
  79. 'pk': obj.last_poster_id,
  80. }
  81. )
  82. }
  83. return None
  84. def get_url(self, obj):
  85. return {
  86. 'index': obj.get_absolute_url(),
  87. 'last_thread': self.get_last_thread_url(obj),
  88. 'last_thread_new': self.get_last_thread_new_url(obj),
  89. 'last_post': self.get_last_post_url(obj),
  90. }
  91. @last_activity_detail
  92. def get_last_thread_url(self, obj):
  93. return obj.get_last_thread_url()
  94. @last_activity_detail
  95. def get_last_thread_new_url(self, obj):
  96. return obj.get_last_thread_new_url()
  97. @last_activity_detail
  98. def get_last_post_url(self, obj):
  99. return obj.get_last_post_url()
  100. class CategoryWithPosterSerializer(CategorySerializer):
  101. last_poster = serializers.SerializerMethodField()
  102. def get_subcategories(self, obj):
  103. try:
  104. return CategoryWithPosterSerializer(obj.subcategories, many=True).data
  105. except AttributeError:
  106. return []
  107. CategoryWithPosterSerializer = CategoryWithPosterSerializer.extend_fields('last_poster')