diff --git a/taiga/projects/stars/services.py b/taiga/projects/stars/services.py index 1d61b7cf..937ac526 100644 --- a/taiga/projects/stars/services.py +++ b/taiga/projects/stars/services.py @@ -6,7 +6,6 @@ from django.contrib.auth import get_user_model from .models import Fan, Stars -@atomic def star(project, user): """Star a project for an user. @@ -16,16 +15,21 @@ def star(project, user): :param project: :class:`~taiga.projects.models.Project` instance. :param user: :class:`~taiga.users.models.User` instance. """ - if not Fan.objects.filter(project=project, user=user).exists(): - Fan.objects.create(project=project, user=user) + + with atomic(): + fan, created = Fan.objects.get_or_create(project=project, + user=user) + if not created: + return + stars, _ = Stars.objects.get_or_create(project=project) stars.count = F('count') + 1 stars.save() -@atomic def unstar(project, user): - """Unstar a project for an user. + """ + Unstar a project for an user. If the user has not starred the project nothing happens so this function can be considered idempotent. @@ -33,16 +37,25 @@ def unstar(project, user): :param project: :class:`~taiga.projects.models.Project` instance. :param user: :class:`~taiga.users.models.User` instance. """ - if Fan.objects.filter(project=project, user=user).exists(): - Fan.objects.filter(project=project, user=user).delete() + + with atomic(): + qs = Fan.objects.filter(project=project, user=user) + if not qs.exists(): + return + + qs.delete() + stars, _ = Stars.objects.get_or_create(project=project) stars.count = F('count') - 1 stars.save() def get_stars(project): - """Get the count of stars a project have.""" - return Stars.objects.filter(project=project).count + """ + Get the count of stars a project have. + """ + instance, _ = Stars.objects.get_or_create(project=project) + return instance.count def get_fans(project_or_id):