serializers.py 3.1 KB

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