Skip to content

Commit f2a23fe

Browse files
authored
Merge pull request #47 from PROCOLLAB-github/dev
Dev
2 parents 0f44706 + f7ef5c7 commit f2a23fe

9 files changed

Lines changed: 151 additions & 46 deletions

File tree

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Generated by Django 4.1.3 on 2022-11-18 11:45
2+
3+
import django.db.models.deletion
4+
from django.conf import settings
5+
from django.db import migrations, models
6+
7+
8+
def set_userachievement_user_to_not_null(apps, schema_editor):
9+
Project = apps.get_model('projects', 'Project')
10+
Project.objects.filter(leader=None).delete()
11+
12+
13+
class Migration(migrations.Migration):
14+
dependencies = [
15+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
16+
("industries", "0001_initial"),
17+
("projects", "0007_remove_collaborator_unique_collaorator_and_more"),
18+
]
19+
20+
operations = [
21+
migrations.AlterField(
22+
model_name="project",
23+
name="description",
24+
field=models.TextField(blank=True, null=True),
25+
),
26+
migrations.AlterField(
27+
model_name="project",
28+
name="image_address",
29+
field=models.URLField(blank=True, null=True),
30+
),
31+
migrations.AlterField(
32+
model_name="project",
33+
name="industry",
34+
field=models.ForeignKey(
35+
blank=True,
36+
null=True,
37+
on_delete=django.db.models.deletion.SET_NULL,
38+
related_name="projects",
39+
to="industries.industry",
40+
),
41+
),
42+
migrations.RunPython(set_userachievement_user_to_not_null),
43+
migrations.AlterField(
44+
model_name="project",
45+
name="leader",
46+
field=models.ForeignKey(
47+
on_delete=django.db.models.deletion.CASCADE,
48+
related_name="leaders_projects",
49+
to=settings.AUTH_USER_MODEL,
50+
),
51+
),
52+
migrations.AlterField(
53+
model_name="project",
54+
name="presentation_address",
55+
field=models.URLField(blank=True, null=True),
56+
),
57+
migrations.AlterField(
58+
model_name="project",
59+
name="region",
60+
field=models.CharField(blank=True, max_length=256, null=True),
61+
),
62+
migrations.AlterField(
63+
model_name="project",
64+
name="short_description",
65+
field=models.TextField(blank=True, null=True),
66+
),
67+
]

projects/models.py

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,24 +31,24 @@ class Project(models.Model):
3131
"""
3232

3333
name = models.CharField(max_length=256, null=True, blank=True)
34-
description = models.TextField(blank=True)
35-
short_description = models.TextField(blank=True)
36-
region = models.CharField(max_length=256, blank=True)
34+
description = models.TextField(null=True, blank=True)
35+
short_description = models.TextField(null=True, blank=True)
36+
region = models.CharField(max_length=256, null=True, blank=True)
3737
step = models.PositiveSmallIntegerField(choices=VERBOSE_STEPS, null=True, blank=True)
3838

3939
industry = models.ForeignKey(
4040
Industry,
4141
on_delete=models.SET_NULL,
4242
null=True,
43+
blank=True,
4344
related_name="projects",
4445
)
45-
presentation_address = models.URLField(blank=True)
46-
image_address = models.URLField(blank=True)
46+
presentation_address = models.URLField(null=True, blank=True)
47+
image_address = models.URLField(null=True, blank=True)
4748

4849
leader = models.ForeignKey(
4950
User,
50-
on_delete=models.SET_NULL,
51-
null=True,
51+
on_delete=models.CASCADE,
5252
related_name="leaders_projects", # projects in which this user is the leader
5353
)
5454

@@ -85,10 +85,7 @@ class Achievement(models.Model):
8585
status = models.CharField(max_length=256, null=False)
8686

8787
project = models.ForeignKey(
88-
Project,
89-
on_delete=models.SET_NULL,
90-
null=True,
91-
related_name="achievements",
88+
Project, on_delete=models.SET_NULL, null=True, related_name="achievements"
9289
)
9390

9491
objects = AchievementManager()

projects/serializers.py

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from industries.models import Industry
44
from projects.models import Project, Achievement, Collaborator
55
from projects.validators import validate_project
6-
from users.models import CustomUser
76
from vacancy.serializers import ProjectVacancyListSerializer
87

98

@@ -95,10 +94,6 @@ class Meta:
9594

9695

9796
class ProjectListSerializer(serializers.ModelSerializer):
98-
def __init__(self, *args, **kwargs):
99-
# might be unnecessary
100-
self.max_collaborator_count = kwargs.pop("max_collaborator_count", 4)
101-
super().__init__(*args, **kwargs)
10297

10398
collaborators = serializers.SerializerMethodField(method_name="get_collaborators")
10499
collaborator_count = serializers.SerializerMethodField(
@@ -111,8 +106,9 @@ def get_collaborator_count(cls, obj):
111106
return len(obj.collaborator_set.all())
112107

113108
def get_collaborators(self, obj):
109+
max_collaborator_count = 4
114110
return CollaboratorSerializer(
115-
instance=obj.collaborator_set.all()[: self.max_collaborator_count], many=True
111+
instance=obj.collaborator_set.all()[:max_collaborator_count], many=True
116112
).data
117113

118114
class Meta:
@@ -144,16 +140,6 @@ def validate(self, data):
144140
super().validate(data)
145141
return validate_project(data)
146142

147-
def create(self, validated_data):
148-
industry = Industry.objects.get(id=validated_data.pop("industry"))
149-
leader = CustomUser.objects.get(id=validated_data.pop("leader"))
150-
project = Project.objects.create(
151-
**validated_data,
152-
industry=industry,
153-
leader=leader,
154-
)
155-
return project
156-
157143

158144
class ProjectIndustrySerializer(serializers.ModelSerializer):
159145
id = serializers.IntegerField()

projects/views.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ def create(self, request, *args, **kwargs):
3030
serializer = self.get_serializer(data=request.data)
3131
serializer.is_valid(raise_exception=True)
3232
# Doesn't work if not explicitly set like this
33-
serializer.validated_data["leader"] = request.user.id
34-
serializer.validated_data["industry"] = request.data["industry"]
33+
serializer.validated_data["leader"] = request.user
3534

3635
self.perform_create(serializer)
3736
headers = self.get_success_headers(serializer.data)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Generated by Django 4.1.3 on 2022-11-18 11:18
2+
3+
from django.conf import settings
4+
from django.db import migrations, models
5+
import django.db.models.deletion
6+
7+
8+
def set_userachievement_user_to_not_null(apps, schema_editor):
9+
UserAchievement = apps.get_model('users', 'UserAchievement')
10+
UserAchievement.objects.filter(user=None).delete()
11+
12+
13+
class Migration(migrations.Migration):
14+
15+
dependencies = [
16+
("users", "0018_alter_customuser_about_me"),
17+
]
18+
19+
operations = [
20+
migrations.RunPython(set_userachievement_user_to_not_null),
21+
migrations.AlterField(
22+
model_name="userachievement",
23+
name="user",
24+
field=models.ForeignKey(
25+
on_delete=django.db.models.deletion.CASCADE,
26+
related_name="achievements",
27+
to=settings.AUTH_USER_MODEL,
28+
),
29+
),
30+
]

users/models.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,14 @@ class CustomUser(AbstractUser):
8282

8383
objects = CustomUserManager()
8484

85-
def get_member_key_skills(self) -> str:
85+
def get_member_key_skills(self) -> list[str]:
8686
if self.user_type == CustomUser.MEMBER:
87-
return str(self.member.key_skills)
88-
return ""
87+
return [
88+
skill.strip()
89+
for skill in self.member.key_skills.split(",")
90+
if skill.strip()
91+
]
92+
return []
8993

9094
def __str__(self):
9195
return f"User<{self.id}> - {self.first_name} {self.last_name}"
@@ -106,8 +110,7 @@ class UserAchievement(models.Model):
106110

107111
user = models.ForeignKey(
108112
CustomUser,
109-
on_delete=models.SET_NULL,
110-
null=True,
113+
on_delete=models.CASCADE,
111114
related_name="achievements",
112115
)
113116

@@ -170,6 +173,9 @@ class Member(models.Model):
170173
Industry, blank=True, related_name="members"
171174
)
172175

176+
def get_key_skills(self) -> list[str]:
177+
return [skill.strip() for skill in self.key_skills.split(",") if skill.strip()]
178+
173179
def __str__(self):
174180
return f"Member<{self.id}> - {self.user.first_name} {self.user.last_name}"
175181

users/permissions.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,6 @@ class IsAchievementOwnerOrReadOnly(BasePermission):
66
Allows access to update only to himself.
77
"""
88

9-
def has_permission(self, request, view) -> bool:
10-
if request.method in SAFE_METHODS or (
11-
request.user and request.user.id == request.data.get("user")
12-
):
13-
return True
14-
return False
15-
169
def has_object_permission(self, request, view, obj):
1710
if request.method in SAFE_METHODS or (obj.user == request.user):
1811
return True

users/serializers.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,22 @@
77
class AchievementListSerializer(serializers.ModelSerializer):
88
class Meta:
99
model = UserAchievement
10-
fields = [
11-
"id",
12-
"title",
13-
"status",
14-
]
10+
fields = ["id", "title", "status"]
11+
# extra_kwargs = {"user": {"write_only": True}}
1512
ref_name = "Users"
1613

1714

15+
class KeySkillsField(serializers.Field):
16+
def to_representation(self, value):
17+
return [skill.strip() for skill in value.split(",") if skill.strip()]
18+
19+
def to_internal_value(self, data):
20+
return ",".join(data)
21+
22+
1823
class MemberSerializer(serializers.ModelSerializer):
24+
key_skills = KeySkillsField()
25+
1926
class Meta:
2027
model = Member
2128
fields = [

users/views.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,26 @@ class AchievementList(ListCreateAPIView):
264264
serializer_class = AchievementListSerializer
265265
permission_classes = [IsAchievementOwnerOrReadOnly]
266266

267+
def create(self, request, *args, **kwargs):
268+
serializer = self.get_serializer(data=request.data)
269+
serializer.is_valid(raise_exception=True)
270+
serializer.validated_data["user"] = request.user
271+
# warning for someone who tries to set user variable (the user will always be yourself anyway)
272+
if (
273+
request.data.get("user") is not None
274+
and request.data.get("user") != request.user.id
275+
):
276+
return Response(
277+
{
278+
"error": "you can't edit USER field for this view since "
279+
"you can't create achievements for other people"
280+
},
281+
status=status.HTTP_403_FORBIDDEN,
282+
)
283+
self.perform_create(serializer)
284+
headers = self.get_success_headers(serializer.data)
285+
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
286+
267287

268288
class AchievementDetail(RetrieveUpdateDestroyAPIView):
269289
queryset = UserAchievement.objects.get_achievements_for_detail_view()

0 commit comments

Comments
 (0)