Skip to content

Commit f6fa147

Browse files
authored
Merge pull request #174 from PROCOLLAB-github/dev
Dev
2 parents 7bb3702 + 619c364 commit f6fa147

11 files changed

Lines changed: 185 additions & 13 deletions

File tree

core/constants.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
ONE_DAY_IN_SECONDS = 60 * 60 * 24
22
ONE_WEEK_IN_SECONDS = ONE_DAY_IN_SECONDS * 7
3+
VIEWS_CACHING_TIMEOUT = 60 * 15
4+
LIKES_CACHING_TIMEOUT = 60 * 15

core/services.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
from django.contrib.auth import get_user_model
22
from django.contrib.contenttypes.models import ContentType
3+
from django.core.cache import cache
34

5+
from core.constants import VIEWS_CACHING_TIMEOUT, LIKES_CACHING_TIMEOUT
46
from core.models import Like, View, Link
57

68
User = get_user_model()
@@ -34,9 +36,15 @@ def get_fans(obj):
3436

3537
def get_likes_count(obj):
3638
obj_type = ContentType.objects.get_for_model(obj)
37-
return User.objects.filter(
38-
likes__content_type=obj_type, likes__object_id=obj.id
39-
).count()
39+
# cache this
40+
likes_count = cache.get(f"likes_count_{obj_type}_{obj.id}")
41+
if likes_count is None:
42+
likes_count = User.objects.filter(
43+
likes__content_type=obj_type, likes__object_id=obj.id
44+
).count()
45+
# cache for LIKES_CACHING_TIMEOUT seconds
46+
cache.set(f"views_count_{obj_type}_{obj.id}", likes_count, LIKES_CACHING_TIMEOUT)
47+
return likes_count
4048

4149

4250
def set_like(obj, user, is_liked):
@@ -76,9 +84,16 @@ def get_viewers(obj):
7684

7785
def get_views_count(obj):
7886
obj_type = ContentType.objects.get_for_model(obj)
79-
return User.objects.filter(
80-
views__content_type=obj_type, views__object_id=obj.id
81-
).count()
87+
# cache this
88+
views_count = cache.get(f"views_count_{obj_type}_{obj.id}")
89+
if views_count is None:
90+
views_count = User.objects.filter(
91+
views__content_type=obj_type, views__object_id=obj.id
92+
).count()
93+
# cache for VIEWS_CACHING_TIMEOUT seconds
94+
cache.set(f"views_count_{obj_type}_{obj.id}", views_count, VIEWS_CACHING_TIMEOUT)
95+
96+
return views_count
8297

8398

8499
def set_viewed(obj, user, is_viewed):

partner_programs/admin.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class PartnerProgramUserProfileAdmin(admin.ModelAdmin):
4747
list_filter = ("partner_program",)
4848
raw_id_fields = (
4949
"user",
50+
"project",
5051
"partner_program",
5152
)
5253
date_hierarchy = "datetime_created"
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Generated by Django 4.2.3 on 2023-07-18 20:25
2+
3+
from django.conf import settings
4+
from django.db import migrations, models
5+
import django.db.models.deletion
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
dependencies = [
11+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
12+
("projects", "0019_alter_project_options_project_hidden_score"),
13+
("partner_programs", "0002_alter_partnerprogram_options_and_more"),
14+
]
15+
16+
operations = [
17+
migrations.AddField(
18+
model_name="partnerprogramuserprofile",
19+
name="project",
20+
field=models.ForeignKey(
21+
null=True,
22+
on_delete=django.db.models.deletion.SET_NULL,
23+
related_name="partner_program_profiles",
24+
to="projects.project",
25+
),
26+
),
27+
migrations.AlterField(
28+
model_name="partnerprogramuserprofile",
29+
name="partner_program",
30+
field=models.ForeignKey(
31+
on_delete=django.db.models.deletion.CASCADE,
32+
related_name="partner_program_profiles",
33+
to="partner_programs.partnerprogram",
34+
),
35+
),
36+
migrations.AlterField(
37+
model_name="partnerprogramuserprofile",
38+
name="user",
39+
field=models.ForeignKey(
40+
null=True,
41+
on_delete=django.db.models.deletion.SET_NULL,
42+
related_name="partner_program_profiles",
43+
to=settings.AUTH_USER_MODEL,
44+
),
45+
),
46+
]

partner_programs/models.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from django.db import models
33

44
from partner_programs.constants import get_default_data_schema
5+
from projects.models import Project
56

67
User = get_user_model()
78

@@ -107,14 +108,22 @@ class PartnerProgramUserProfile(models.Model):
107108
"""
108109

109110
user = models.ForeignKey(
110-
User, on_delete=models.CASCADE, related_name="partner_program_profile"
111+
User,
112+
on_delete=models.SET_NULL,
113+
related_name="partner_program_profiles",
114+
null=True,
115+
)
116+
project = models.ForeignKey(
117+
Project,
118+
on_delete=models.SET_NULL,
119+
related_name="partner_program_profiles",
120+
null=True,
111121
)
112122
partner_program = models.ForeignKey(
113123
PartnerProgram,
114124
on_delete=models.CASCADE,
115-
related_name="partner_program_user_profile",
125+
related_name="partner_program_profiles",
116126
)
117-
# TODO: add amount of projects of this Program that user created
118127
partner_program_data = models.JSONField()
119128
datetime_created = models.DateTimeField(auto_now_add=True)
120129
datetime_updated = models.DateTimeField(auto_now=True)
@@ -128,6 +137,4 @@ class Meta:
128137
)
129138

130139
def __str__(self):
131-
return (
132-
f"PartnerProgramUserProfile<{self.pk}> - {self.user} {self.partner_program}"
133-
)
140+
return f"PartnerProgramUserProfile<{self.pk}> - {self.user} {self.project} {self.partner_program}"

partner_programs/serializers.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,13 @@ class PartnerProgramUserSerializer(serializers.Serializer):
126126

127127
class PartnerProgramDataSchemaSerializer(serializers.Serializer):
128128
data_schema = serializers.JSONField(required=True)
129+
130+
131+
class UserProgramsSerializer(serializers.ModelSerializer):
132+
class Meta:
133+
model = PartnerProgram
134+
fields = [
135+
"id",
136+
"name",
137+
"tag",
138+
]

partner_programs/views.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ def post(self, request, *args, **kwargs):
9696
except PartnerProgram.DoesNotExist:
9797
return Response(status=status.HTTP_404_NOT_FOUND)
9898

99+
def get(self, request, *args, **kwargs):
100+
return Response(status=status.HTTP_200_OK)
101+
99102

100103
class PartnerProgramRegister(generics.GenericAPIView):
101104
"""

projects/helpers.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from django.contrib.auth import get_user_model
44

5+
from partner_programs.models import PartnerProgram, PartnerProgramUserProfile
56
from projects.constants import RECOMMENDATIONS_COUNT
67
from projects.models import Project, ProjectLink, Achievement
78

@@ -84,3 +85,16 @@ def update_links(links, pk):
8485
for link in links
8586
]
8687
)
88+
89+
90+
def update_partner_program(
91+
partner_program_id: int, user: "User", instance: "Project"
92+
) -> None:
93+
if partner_program_id:
94+
partner_program = PartnerProgram.objects.get(pk=partner_program_id)
95+
partner_program_profile = PartnerProgramUserProfile.objects.get(
96+
user=user,
97+
partner_program=partner_program,
98+
)
99+
partner_program_profile.project = instance
100+
partner_program_profile.save()

projects/views.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,14 @@
99
from core.permissions import IsStaffOrReadOnly
1010
from core.serializers import SetLikedSerializer
1111
from core.services import add_view, set_like
12+
from partner_programs.models import PartnerProgram, PartnerProgramUserProfile
1213
from projects.filters import ProjectFilter
1314
from projects.constants import VERBOSE_STEPS
14-
from projects.helpers import get_recommended_users, check_related_fields_update
15+
from projects.helpers import (
16+
get_recommended_users,
17+
check_related_fields_update,
18+
update_partner_program,
19+
)
1520
from projects.models import Project, Achievement, ProjectNews
1621
from projects.pagination import ProjectNewsPagination
1722
from projects.permissions import (
@@ -51,6 +56,21 @@ def create(self, request, *args, **kwargs):
5156
serializer.validated_data["leader"] = request.user
5257

5358
self.perform_create(serializer)
59+
60+
try:
61+
partner_program_id = request.data.get("partner_program_id")
62+
update_partner_program(partner_program_id, request.user, serializer.instance)
63+
except PartnerProgram.DoesNotExist:
64+
return Response(
65+
{"detail": "Partner program with this id does not exist"},
66+
status=status.HTTP_400_BAD_REQUEST,
67+
)
68+
except PartnerProgramUserProfile.DoesNotExist:
69+
return Response(
70+
{"detail": "User is not a member of this partner program"},
71+
status=status.HTTP_400_BAD_REQUEST,
72+
)
73+
5474
headers = self.get_success_headers(serializer.data)
5575
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
5676

@@ -101,6 +121,20 @@ def retrieve(self, request, *args, **kwargs):
101121
return Response(serializer.data)
102122

103123
def put(self, request, pk, **kwargs):
124+
# fixme: add partner_program_id to docs
125+
try:
126+
partner_program_id = request.data.get("partner_program_id")
127+
update_partner_program(partner_program_id, request.user, self.get_object())
128+
except PartnerProgram.DoesNotExist:
129+
return Response(
130+
{"detail": "Partner program with this id does not exist"},
131+
status=status.HTTP_400_BAD_REQUEST,
132+
)
133+
except PartnerProgramUserProfile.DoesNotExist:
134+
return Response(
135+
{"detail": "User is not a member of this partner program"},
136+
status=status.HTTP_400_BAD_REQUEST,
137+
)
104138
check_related_fields_update(request.data, pk)
105139
return super(ProjectDetail, self).put(request, pk)
106140

users/urls.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
RegisteredEventsList,
1919
SetUserOnboardingStage,
2020
ResendVerifyEmail,
21+
CurrentUserPrograms,
22+
CurrentUserProgramsTags,
2123
)
2224

2325
app_name = "users"
@@ -35,6 +37,8 @@
3537
path("users/<int:pk>/set_onboarding_stage/", SetUserOnboardingStage.as_view()),
3638
path("users/reset-password/", EmailResetPassword.as_view()),
3739
path("users/current/", CurrentUser.as_view()),
40+
path("users/current/programs/", CurrentUserPrograms.as_view()),
41+
path("users/current/programs/tags/", CurrentUserProgramsTags.as_view()),
3842
path("users/current/events/", RegisteredEventsList.as_view()),
3943
path("users/achievements/", AchievementList.as_view()),
4044
path("users/achievements/<int:pk>/", AchievementDetail.as_view()),

0 commit comments

Comments
 (0)