Skip to content

Commit f56d7a6

Browse files
authored
Merge pull request #362 from PROCOLLAB-github/dev-to-master
Dev
2 parents 9268298 + fccbe87 commit f56d7a6

19 files changed

Lines changed: 182 additions & 58 deletions

File tree

.github/workflows/dev-ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ on:
55
branches:
66
- dev
77
workflow_dispatch:
8-
8+
99
jobs:
1010
deploy:
1111
runs-on: ubuntu-latest

core/fields.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33

44
class CustomListField(serializers.ListField):
5-
def to_representation(self, data):
5+
def to_representation(self, data) -> list:
66
return [value.strip() for value in data.split(",") if value.strip()]
77

8-
def to_internal_value(self, data):
8+
def to_internal_value(self, data) -> str:
99
return ",".join(data)

core/models.py

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from django.contrib.contenttypes.models import ContentType
44
from django.db import models
55
from django.db.models import Model
6+
from django_stubs_ext.db.models import TypedModelMeta
67

78
User = get_user_model()
89

@@ -23,7 +24,7 @@ class Link(Model):
2324
object_id = models.PositiveIntegerField()
2425
content_object = GenericForeignKey("content_type", "object_id")
2526

26-
class Meta:
27+
class Meta(TypedModelMeta):
2728
unique_together = (
2829
"link",
2930
"content_type",
@@ -32,7 +33,7 @@ class Meta:
3233
verbose_name = "Ссылка"
3334
verbose_name_plural = "Ссылки"
3435

35-
def __str__(self):
36+
def __str__(self) -> str:
3637
return f"Link for {self.content_object} - {self.link}"
3738

3839

@@ -54,7 +55,7 @@ class Like(Model):
5455
object_id = models.PositiveIntegerField()
5556
content_object = GenericForeignKey("content_type", "object_id")
5657

57-
class Meta:
58+
class Meta(TypedModelMeta):
5859
unique_together = (
5960
"user",
6061
"content_type",
@@ -63,7 +64,7 @@ class Meta:
6364
verbose_name = "Лайк"
6465
verbose_name_plural = "Лайки"
6566

66-
def __str__(self):
67+
def __str__(self) -> str:
6768
return f"Like<{self.user} - {self.content_object}>"
6869

6970

@@ -88,7 +89,7 @@ class View(Model):
8889
object_id = models.PositiveIntegerField()
8990
content_object = GenericForeignKey("content_type", "object_id")
9091

91-
class Meta:
92+
class Meta(TypedModelMeta):
9293
unique_together = (
9394
"user",
9495
"content_type",
@@ -97,7 +98,7 @@ class Meta:
9798
verbose_name = "Просмотр"
9899
verbose_name_plural = "Просмотры"
99100

100-
def __str__(self):
101+
def __str__(self) -> str:
101102
return f"View<{self.user} - {self.content_object}>"
102103

103104

@@ -108,10 +109,10 @@ class SkillCategory(models.Model):
108109

109110
name = models.CharField(max_length=256, null=False)
110111

111-
def __str__(self):
112+
def __str__(self) -> str:
112113
return self.name
113114

114-
class Meta:
115+
class Meta(TypedModelMeta):
115116
verbose_name = "Категория навыка"
116117
verbose_name_plural = "Категории навыков"
117118
ordering = ["name"]
@@ -129,13 +130,13 @@ class Skill(models.Model):
129130
related_name="skills",
130131
)
131132

132-
def __str__(self):
133+
def __str__(self) -> str:
133134
return self.name
134135

135-
def __repr__(self):
136+
def __repr__(self) -> str:
136137
return f"Skill<name={self.name},id={self.id}>"
137138

138-
class Meta:
139+
class Meta(TypedModelMeta):
139140
verbose_name = "Навык"
140141
verbose_name_plural = "Навыки"
141142
ordering = ["id", "category", "name"]
@@ -160,18 +161,18 @@ class SkillToObject(models.Model):
160161
object_id = models.PositiveIntegerField()
161162
content_object = GenericForeignKey("content_type", "object_id")
162163

163-
class Meta:
164+
class Meta(TypedModelMeta):
164165
verbose_name = "Ссылка на навык"
165166
verbose_name_plural = "Ссылки на навыки"
166167

167168

168169
class SpecializationCategory(models.Model):
169170
name = models.TextField()
170171

171-
def __str__(self):
172+
def __str__(self) -> str:
172173
return self.name
173174

174-
class Meta:
175+
class Meta(TypedModelMeta):
175176
verbose_name = "Категория специализации"
176177
verbose_name_plural = "Категории специализаций"
177178

@@ -182,10 +183,10 @@ class Specialization(models.Model):
182183
SpecializationCategory, related_name="specializations", on_delete=models.CASCADE
183184
)
184185

185-
def __str__(self):
186+
def __str__(self) -> str:
186187
return self.name
187188

188-
class Meta:
189+
class Meta(TypedModelMeta):
189190
verbose_name = "Специализация"
190191
verbose_name_plural = "Специализации"
191192

invites/models.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from invites.managers import InviteManager
44
from projects.models import Project
55
from users.models import CustomUser
6+
from django_stubs_ext.db.models import TypedModelMeta
67

78

89
class Invite(models.Model):
@@ -37,10 +38,10 @@ class Invite(models.Model):
3738

3839
objects = InviteManager()
3940

40-
def __str__(self):
41+
def __str__(self) -> str:
4142
return f'Invite from project "{self.project.name}" to {self.user.get_full_name()}'
4243

43-
class Meta:
44+
class Meta(TypedModelMeta):
4445
verbose_name = "Приглашение"
4546
verbose_name_plural = "Приглашения"
4647
ordering = ["-datetime_created"]

invites/serializers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from users.serializers import UserDetailSerializer
66

77

8-
class InviteListSerializer(serializers.ModelSerializer):
8+
class InviteListSerializer(serializers.ModelSerializer[Invite]):
99
class Meta:
1010
model = Invite
1111
fields = [
@@ -18,7 +18,7 @@ class Meta:
1818
]
1919

2020

21-
class InviteDetailSerializer(serializers.ModelSerializer):
21+
class InviteDetailSerializer(serializers.ModelSerializer[Invite]):
2222
user = UserDetailSerializer(many=False, read_only=True)
2323
project = ProjectListSerializer(many=False, read_only=True)
2424

news/managers.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
from django.contrib.contenttypes.models import ContentType
22
from django.db import models
3+
from django.db.models.query import QuerySet
4+
import typing
5+
if typing.TYPE_CHECKING:
6+
from news.models import News
37

48

59
class NewsManager(models.Manager):
6-
def get_news(self, obj):
10+
def get_news(self, obj: models.Model) -> QuerySet["News"]:
711
obj_type = ContentType.objects.get_for_model(obj)
812
return self.get_queryset().filter(content_type=obj_type, object_id=obj.pk)
913

10-
def add_news(self, obj, **kwargs):
14+
def add_news(self, obj: models.Model, **kwargs) -> "News":
1115
obj_type = ContentType.objects.get_for_model(obj)
1216
kwargs = dict(kwargs)
1317
files = kwargs.pop("files", [])

news/mixins.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from django.contrib.auth import get_user_model
2-
2+
from django.db.models.query import QuerySet
33
from news.models import News
44
from partner_programs.models import PartnerProgram
55
from projects.models import Project
@@ -12,7 +12,7 @@ class NewsQuerysetMixin:
1212
Mixin for getting queryset for news
1313
"""
1414

15-
def get_queryset_for_project(self):
15+
def get_queryset_for_project(self) -> QuerySet[News]:
1616
"""Returns queryset of news for project"""
1717
project_pk = self.kwargs.get("project_pk")
1818
try:
@@ -25,7 +25,7 @@ def get_queryset_for_project(self):
2525
text="", content_type__model="project"
2626
)
2727

28-
def get_queryset_for_program(self):
28+
def get_queryset_for_program(self) -> QuerySet[News]:
2929
"""Returns queryset of news for partner program"""
3030
partnerprogram_pk = self.kwargs.get("partnerprogram_pk")
3131
try:
@@ -35,7 +35,7 @@ def get_queryset_for_program(self):
3535
return News.objects.none()
3636
return News.objects.get_news(obj=program)
3737

38-
def get_queryset_for_user(self):
38+
def get_queryset_for_user(self) -> QuerySet[News]:
3939
"""Returns queryset of news for user"""
4040
user_pk = self.kwargs.get("user_pk")
4141
try:
@@ -45,7 +45,7 @@ def get_queryset_for_user(self):
4545
return News.objects.none()
4646
return News.objects.get_news(obj=user)
4747

48-
def get_queryset(self):
48+
def get_queryset(self) -> QuerySet[News] | None:
4949
"""Chooses what queryset to return - for project, program or user"""
5050
if self.kwargs.get("project_pk") is not None:
5151
return self.get_queryset_for_project()

news/models.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from core.models import Like, View
77
from files.models import UserFile
88
from news.managers import NewsManager
9+
from django_stubs_ext.db.models import TypedModelMeta
910

1011

1112
class News(models.Model):
@@ -43,7 +44,7 @@ class News(models.Model):
4344

4445
objects = NewsManager()
4546

46-
class Meta:
47+
class Meta(TypedModelMeta):
4748
verbose_name = "Новость"
4849
verbose_name_plural = "Новости"
4950
ordering = ["-datetime_created"]

news/serializers.py

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
User = get_user_model()
1111

1212

13-
class NewsListCreateSerializer(serializers.ModelSerializer):
13+
class NewsListCreateSerializer(serializers.ModelSerializer[News]):
1414
class Meta:
1515
model = News
1616
fields = [
@@ -19,7 +19,7 @@ class Meta:
1919
]
2020

2121

22-
class NewsListSerializer(serializers.ModelSerializer):
22+
class NewsListSerializer(serializers.ModelSerializer[News]):
2323
views_count = serializers.SerializerMethodField()
2424
likes_count = serializers.SerializerMethodField()
2525
name = serializers.SerializerMethodField()
@@ -60,6 +60,71 @@ class Meta:
6060
]
6161

6262

63+
64+
class NewsFeedListSerializer(serializers.ModelSerializer):
65+
name = serializers.SerializerMethodField()
66+
image_address = serializers.SerializerMethodField()
67+
is_user_liked = serializers.SerializerMethodField()
68+
files = UserFileSerializer(many=True)
69+
views_count = serializers.SerializerMethodField()
70+
likes_count = serializers.SerializerMethodField()
71+
content_object = serializers.SerializerMethodField()
72+
type_model = serializers.SerializerMethodField()
73+
74+
def get_type_model(self, obj) -> str:
75+
model_type = CONTENT_OBJECT_MAPPING[obj.content_type.model]
76+
if obj.text != "" and model_type == "project":
77+
return "news"
78+
return model_type
79+
80+
def get_content_object(self, obj) -> dict:
81+
type_model = obj.content_type.model
82+
if obj.text != "" and self.get_type_model(obj) == "project":
83+
type_model = "news"
84+
serializer = CONTENT_OBJECT_SERIALIZER_MAPPING[type_model](obj.content_object)
85+
return serializer.data
86+
87+
def get_views_count(self, obj):
88+
return get_views_count(obj)
89+
90+
def get_likes_count(self, obj):
91+
return get_likes_count(obj)
92+
93+
def get_name(self, obj):
94+
if obj.content_type.model == CustomUser.__name__.lower():
95+
return f"{obj.content_object.first_name} {obj.content_object.last_name}"
96+
elif obj.text != "" and obj.content_type.model == Project.__name__.lower():
97+
return f"{obj.content_object.name}"
98+
99+
def get_image_address(self, obj):
100+
return NewsMapping.get_image_address(obj.content_object)
101+
102+
def get_is_user_liked(self, obj):
103+
user = self.context.get("user")
104+
if user:
105+
return is_fan(obj, user)
106+
return False
107+
108+
class Meta:
109+
model = News
110+
fields = [
111+
"id",
112+
"name",
113+
"image_address",
114+
"text",
115+
"datetime_created",
116+
"views_count",
117+
"likes_count",
118+
"files",
119+
"is_user_liked",
120+
"content_object",
121+
"type_model",
122+
]
123+
read_only_fields = ["views_count", "likes_count", "type_model"]
124+
125+
126+
127+
63128
class NewsDetailSerializer(serializers.ModelSerializer):
64129
views_count = serializers.SerializerMethodField()
65130
likes_count = serializers.SerializerMethodField()

0 commit comments

Comments
 (0)