serializers.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. from django.core.urlresolvers import reverse
  2. from rest_framework import serializers
  3. from misago.core.utils import format_plaintext_for_html
  4. from misago.categories.models import Category
  5. __all__ = [
  6. 'BasicCategorySerializer',
  7. 'IndexCategorySerializer',
  8. 'CategorySerializer',
  9. ]
  10. def last_activity_detail(f):
  11. """util for serializing last activity details"""
  12. def decorator(self, obj):
  13. if not obj.last_thread_id:
  14. return None
  15. acl = self.get_acl(obj)
  16. if not all((
  17. acl.get('can_see'),
  18. acl.get('can_browse'),
  19. acl.get('can_see_all_threads')
  20. )):
  21. return None
  22. return f(self, obj)
  23. return decorator
  24. class CategorySerializer(serializers.ModelSerializer):
  25. parent = serializers.SerializerMethodField()
  26. description = serializers.SerializerMethodField()
  27. is_read = serializers.SerializerMethodField()
  28. subcategories = serializers.SerializerMethodField()
  29. absolute_url = serializers.SerializerMethodField()
  30. last_poster_url = serializers.SerializerMethodField()
  31. last_post_url = serializers.SerializerMethodField()
  32. last_thread_url = serializers.SerializerMethodField()
  33. acl = serializers.SerializerMethodField()
  34. api_url = serializers.SerializerMethodField()
  35. class Meta:
  36. model = Category
  37. fields = (
  38. 'id',
  39. 'parent',
  40. 'name',
  41. 'description',
  42. 'is_closed',
  43. 'threads',
  44. 'posts',
  45. 'last_post_on',
  46. 'last_thread_title',
  47. 'last_poster_name',
  48. 'css_class',
  49. 'is_read',
  50. 'subcategories',
  51. 'absolute_url',
  52. 'last_thread_url',
  53. 'last_post_url',
  54. 'last_poster_url',
  55. 'acl',
  56. 'api_url',
  57. 'level',
  58. 'lft',
  59. 'rght',
  60. )
  61. def get_parent(self, obj):
  62. try:
  63. if obj.parent:
  64. return BasicCategorySerializer(obj.parent).data
  65. else:
  66. return None
  67. except AttributeError:
  68. return None
  69. def get_description(self, obj):
  70. if obj.description:
  71. return {
  72. 'plain': obj.description,
  73. 'html': format_plaintext_for_html(obj.description),
  74. }
  75. else:
  76. return None
  77. def get_is_read(self, obj):
  78. try:
  79. return obj.is_read
  80. except AttributeError:
  81. return None
  82. def get_subcategories(self, obj):
  83. try:
  84. return CategorySerializer(obj.subcategories, many=True).data
  85. except AttributeError:
  86. return []
  87. def get_absolute_url(self, obj):
  88. return obj.get_absolute_url()
  89. @last_activity_detail
  90. def get_last_thread_url(self, obj):
  91. return obj.get_last_thread_url()
  92. @last_activity_detail
  93. def get_last_post_url(self, obj):
  94. return obj.get_last_post_url()
  95. @last_activity_detail
  96. def get_last_poster_url(self, obj):
  97. if obj.last_poster_id:
  98. return reverse('misago:user', kwargs={
  99. 'slug': obj.last_poster_slug,
  100. 'pk': obj.last_poster_id,
  101. })
  102. else:
  103. return None
  104. def get_acl(self, obj):
  105. try:
  106. return obj.acl
  107. except AttributeError:
  108. return {}
  109. def get_api_url(self, obj):
  110. return {
  111. 'read': obj.get_api_read_url(),
  112. }
  113. class IndexCategorySerializer(CategorySerializer):
  114. class Meta:
  115. model = Category
  116. fields = (
  117. 'id',
  118. 'parent',
  119. 'name',
  120. 'description',
  121. 'is_closed',
  122. 'css_class',
  123. 'absolute_url',
  124. 'api_url',
  125. 'level',
  126. 'lft',
  127. 'rght',
  128. )
  129. class BasicCategorySerializer(CategorySerializer):
  130. class Meta:
  131. model = Category
  132. fields = (
  133. 'id',
  134. 'name',
  135. 'is_closed',
  136. 'css_class',
  137. 'absolute_url',
  138. 'level',
  139. 'lft',
  140. 'rght',
  141. )