services.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. # Copyright (C) 2014 Andrey Antukh <niwi@niwi.be>
  2. # Copyright (C) 2014 Jesús Espino <jespinog@gmail.com>
  3. # Copyright (C) 2014 David Barragán <bameda@dbarragan.com>
  4. # Copyright (C) 2014 Anler Hernández <hello@anler.me>
  5. # This program is free software: you can redistribute it and/or modify
  6. # it under the terms of the GNU Affero General Public License as
  7. # published by the Free Software Foundation, either version 3 of the
  8. # License, or (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU Affero General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU Affero General Public License
  16. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. from django.db.models import F
  18. from django.db.transaction import atomic
  19. from django.apps import apps
  20. from django.contrib.auth import get_user_model
  21. from .models import Votes, Vote
  22. def add_vote(obj, user):
  23. """Add a vote to an object.
  24. If the user has already voted the object nothing happends, so this function can be considered
  25. idempotent.
  26. :param obj: Any Django model instance.
  27. :param user: User adding the vote. :class:`~taiga.users.models.User` instance.
  28. """
  29. obj_type = apps.get_model("contenttypes", "ContentType").objects.get_for_model(obj)
  30. with atomic():
  31. vote, created = Vote.objects.get_or_create(content_type=obj_type, object_id=obj.id, user=user)
  32. if not created:
  33. return
  34. votes, _ = Votes.objects.get_or_create(content_type=obj_type, object_id=obj.id)
  35. votes.count = F('count') + 1
  36. votes.save()
  37. return vote
  38. def remove_vote(obj, user):
  39. """Remove an user vote from an object.
  40. If the user has not voted the object nothing happens so this function can be considered
  41. idempotent.
  42. :param obj: Any Django model instance.
  43. :param user: User removing her vote. :class:`~taiga.users.models.User` instance.
  44. """
  45. obj_type = apps.get_model("contenttypes", "ContentType").objects.get_for_model(obj)
  46. with atomic():
  47. qs = Vote.objects.filter(content_type=obj_type, object_id=obj.id, user=user)
  48. if not qs.exists():
  49. return
  50. qs.delete()
  51. votes, _ = Votes.objects.get_or_create(content_type=obj_type, object_id=obj.id)
  52. votes.count = F('count') - 1
  53. votes.save()
  54. def get_voters(obj):
  55. """Get the voters of an object.
  56. :param obj: Any Django model instance.
  57. :return: User queryset object representing the users that voted the object.
  58. """
  59. obj_type = apps.get_model("contenttypes", "ContentType").objects.get_for_model(obj)
  60. return get_user_model().objects.filter(votes__content_type=obj_type, votes__object_id=obj.id)
  61. def get_votes(obj):
  62. """Get the number of votes an object has.
  63. :param obj: Any Django model instance.
  64. :return: Number of votes or `0` if the object has no votes at all.
  65. """
  66. obj_type = apps.get_model("contenttypes", "ContentType").objects.get_for_model(obj)
  67. try:
  68. return Votes.objects.get(content_type=obj_type, object_id=obj.id).count
  69. except Votes.DoesNotExist:
  70. return 0
  71. def get_voted(user_or_id, model):
  72. """Get the objects voted by an user.
  73. :param user_or_id: :class:`~taiga.users.models.User` instance or id.
  74. :param model: Show only objects of this kind. Can be any Django model class.
  75. :return: Queryset of objects representing the votes of the user.
  76. """
  77. obj_type = apps.get_model("contenttypes", "ContentType").objects.get_for_model(model)
  78. conditions = ('votes_vote.content_type_id = %s',
  79. '%s.id = votes_vote.object_id' % model._meta.db_table,
  80. 'votes_vote.user_id = %s')
  81. if isinstance(user_or_id, get_user_model()):
  82. user_id = user_or_id.id
  83. else:
  84. user_id = user_or_id
  85. return model.objects.extra(where=conditions, tables=('votes_vote',),
  86. params=(obj_type.id, user_id))