List fans and starred projects

List project fans:

     /projects/<project id>/fans
     /projects/<project id>/fans/<user id>

List user starred projects:

     /users/<user id>/starred
     /users/<user id>/starred/<project id>

Also a "star" field with the stars count of a project is included in the
project detail and list responses.
remotes/origin/enhancement/email-actions
Anler Hp 2014-05-27 17:24:57 +02:00
parent b56dfe7cf5
commit 34f0dd6f76
9 changed files with 128 additions and 7 deletions

View File

@ -324,3 +324,21 @@ class ProjectTemplateViewSet(ModelCrudViewSet):
def get_queryset(self): def get_queryset(self):
return models.ProjectTemplate.objects.all() return models.ProjectTemplate.objects.all()
class FansViewSet(ModelCrudViewSet):
serializer_class = serializers.FanSerializer
list_serializer_class = serializers.FanSerializer
permission_classes = (IsAuthenticated,)
def get_queryset(self):
return stars.get_fans(self.kwargs.get("project_id"))
class StarredViewSet(ModelCrudViewSet):
serializer_class = serializers.StarredSerializer
list_serializer_class = serializers.StarredSerializer
permission_classes = (IsAuthenticated,)
def get_queryset(self):
return stars.get_starred(self.kwargs.get("user_id"))

View File

@ -19,7 +19,7 @@ from rest_framework import serializers
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from taiga.base.serializers import PickleField, JsonField from taiga.base.serializers import PickleField, JsonField
from taiga.users.models import Role from taiga.users.models import Role, User
from . import models from . import models
@ -84,6 +84,7 @@ class ProjectMembershipSerializer(serializers.ModelSerializer):
class ProjectSerializer(serializers.ModelSerializer): class ProjectSerializer(serializers.ModelSerializer):
tags = PickleField(required=False) tags = PickleField(required=False)
stars = serializers.IntegerField(source="stars.count")
class Meta: class Meta:
model = models.Project model = models.Project
@ -150,3 +151,17 @@ class ProjectTemplateSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = models.ProjectTemplate model = models.ProjectTemplate
class FanSerializer(serializers.ModelSerializer):
full_name = serializers.CharField(source='get_full_name', required=False)
class Meta:
model = User
fields = ('id', 'username', 'first_name', 'last_name', 'full_name')
class StarredSerializer(serializers.ModelSerializer):
class Meta:
model = models.Project
fields = ['id', 'name', 'slug']

View File

@ -1 +1 @@
from .services import star, unstar from .services import star, unstar, get_fans, get_starred

View File

@ -24,7 +24,7 @@ class Fan(models.Model):
class Stars(models.Model): class Stars(models.Model):
project = models.OneToOneField("projects.Project", null=False, blank=False, project = models.OneToOneField("projects.Project", null=False, blank=False,
verbose_name=_("project")) related_name="stars", verbose_name=_("project"))
count = models.PositiveIntegerField(null=False, blank=False, default=0, count = models.PositiveIntegerField(null=False, blank=False, default=0,
verbose_name=_("count")) verbose_name=_("count"))

View File

@ -45,11 +45,23 @@ def get_stars(project):
return Stars.objects.filter(project=project).count return Stars.objects.filter(project=project).count
def get_fans(project): def get_fans(project_or_id):
"""Get the fans a project have.""" """Get the fans a project have."""
return get_user_model().objects.filter(fans__project=project) qs = get_user_model().objects.get_queryset()
if isinstance(project_or_id, int):
qs = qs.filter(fans__project_id=project_or_id)
else:
qs = qs.filter(fans__project=project_or_id)
return qs
def get_starred_projects(user): def get_starred(user_or_id):
"""Get the projects an user has starred.""" """Get the projects an user has starred."""
return Project.objects.filter(fans__user=user) qs = Project.objects.get_queryset()
if isinstance(user_or_id, int):
qs = qs.filter(fans__user_id=user_or_id)
else:
qs = qs.filter(fans__user=user_or_id)
return qs

View File

@ -59,9 +59,13 @@ from taiga.projects.api import IssueTypeViewSet
from taiga.projects.api import PriorityViewSet from taiga.projects.api import PriorityViewSet
from taiga.projects.api import SeverityViewSet from taiga.projects.api import SeverityViewSet
from taiga.projects.api import ProjectTemplateViewSet from taiga.projects.api import ProjectTemplateViewSet
from taiga.projects.api import FansViewSet
from taiga.projects.api import StarredViewSet
router.register(r"roles", RolesViewSet, base_name="roles") router.register(r"roles", RolesViewSet, base_name="roles")
router.register(r"projects", ProjectViewSet, base_name="projects") router.register(r"projects", ProjectViewSet, base_name="projects")
router.register(r"projects/(?P<project_id>\d+)/fans", FansViewSet, base_name="project-fans")
router.register(r"users/(?P<user_id>\d+)/starred", StarredViewSet, base_name="user-starred")
router.register(r"project-templates", ProjectTemplateViewSet, base_name="project-templates") router.register(r"project-templates", ProjectTemplateViewSet, base_name="project-templates")
router.register(r"memberships", MembershipViewSet, base_name="memberships") router.register(r"memberships", MembershipViewSet, base_name="memberships")
router.register(r"invitations", InvitationViewSet, base_name="invitations") router.register(r"invitations", InvitationViewSet, base_name="invitations")

View File

@ -18,6 +18,8 @@ from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import Permission from django.contrib.auth.models import Permission
from rest_framework import serializers from rest_framework import serializers
from taiga.projects.models import Project
from .models import User, Role from .models import User, Role

View File

@ -164,3 +164,10 @@ class FanFactory(Factory):
project = factory.SubFactory("tests.factories.ProjectFactory") project = factory.SubFactory("tests.factories.ProjectFactory")
user = factory.SubFactory("tests.factories.UserFactory") user = factory.SubFactory("tests.factories.UserFactory")
class StarsFactory(Factory):
FACTORY_FOR = taiga.projects.stars.models.Stars
project = factory.SubFactory("tests.factories.ProjectFactory")
count = 0

View File

@ -52,3 +52,66 @@ def test_project_member_unstar_project(client):
response = client.post(url) response = client.post(url)
assert response.status_code == 200 assert response.status_code == 200
def test_list_project_fans(client):
user = f.UserFactory.create()
project = f.ProjectFactory.create(owner=user)
fan = f.FanFactory.create(project=project)
url = reverse("project-fans-list", args=(project.id,))
client.login(user)
response = client.get(url)
assert response.status_code == 200
assert response.data[0]['id'] == fan.user.id
def test_get_project_fan(client):
user = f.UserFactory.create()
project = f.ProjectFactory.create(owner=user)
fan = f.FanFactory.create(project=project)
url = reverse("project-fans-detail", args=(project.id, fan.user.id))
client.login(user)
response = client.get(url)
assert response.status_code == 200
assert response.data['id'] == fan.user.id
def test_list_user_starred_projects(client):
user = f.UserFactory.create()
fan = f.FanFactory.create(user=user)
url = reverse("user-starred-list", args=(user.id,))
client.login(user)
response = client.get(url)
assert response.status_code == 200
assert response.data[0]['id'] == fan.project.id
def test_get_user_starred_project(client):
user = f.UserFactory.create()
fan = f.FanFactory.create(user=user)
url = reverse("user-starred-detail", args=(user.id, fan.project.id))
client.login(user)
response = client.get(url)
assert response.status_code == 200
assert response.data['id'] == fan.project.id
def test_get_project_stars(client):
user = f.UserFactory.create()
project = f.ProjectFactory.create(owner=user)
f.StarsFactory.create(project=project, count=5)
url = reverse("projects-detail", args=(project.id,))
client.login(user)
response = client.get(url)
assert response.status_code == 200
assert response.data['stars'] == 5