Skip to content

Commit 4e78a64

Browse files
authored
Merge pull request #151 from PROCOLLAB-github/feature/auto-project-covers
Автоматическая установка обложек проектов
2 parents 9b784a0 + 434aeb4 commit 4e78a64

3 files changed

Lines changed: 151 additions & 1 deletion

File tree

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# Generated by Django 4.2.3 on 2023-09-07 07:13
2+
3+
from django.db import migrations, models
4+
import django.db.models.deletion
5+
import projects.models
6+
7+
# Generated by Django 4.1.3 on 2023-06-27 11:46
8+
import django
9+
from django.db import migrations, models
10+
import projects.models
11+
12+
13+
def create_default_project_cover(apps, schema_editor):
14+
# create a random default cover using a random UserFile
15+
DefaultProjectCover = apps.get_model("projects", "DefaultProjectCover")
16+
default_cover = DefaultProjectCover.objects.create()
17+
18+
19+
class Migration(migrations.Migration):
20+
21+
dependencies = [
22+
("projects", "0018_alter_defaultprojectcover_image_alter_project_cover"),
23+
]
24+
25+
operations = [
26+
migrations.RunPython(create_default_project_cover),
27+
migrations.AlterField(
28+
model_name="project",
29+
name="cover",
30+
field=models.ForeignKey(
31+
default=projects.models.DefaultProjectCover.get_random_file,
32+
on_delete=django.db.models.deletion.SET_DEFAULT,
33+
related_name="project_cover",
34+
to="files.userfile",
35+
null=True,
36+
blank=True
37+
),
38+
),
39+
]
40+
41+
class Migration(migrations.Migration):
42+
43+
dependencies = [
44+
("files", "0005_alter_userfile_options"),
45+
("projects", "0019_alter_project_options_project_hidden_score"),
46+
]
47+
48+
operations = [
49+
migrations.CreateModel(
50+
name="DefaultProjectCover",
51+
fields=[
52+
(
53+
"id",
54+
models.BigAutoField(
55+
auto_created=True,
56+
primary_key=True,
57+
serialize=False,
58+
verbose_name="ID",
59+
),
60+
),
61+
(
62+
"datetime_created",
63+
models.DateTimeField(auto_now_add=True, verbose_name="Дата создания"),
64+
),
65+
(
66+
"datetime_updated",
67+
models.DateTimeField(auto_now=True, verbose_name="Дата изменения"),
68+
),
69+
(
70+
"image",
71+
models.ForeignKey(
72+
blank=True,
73+
null=True,
74+
on_delete=django.db.models.deletion.CASCADE,
75+
related_name="default_covers",
76+
to="files.userfile",
77+
),
78+
),
79+
],
80+
options={
81+
"verbose_name": "Обложка проекта",
82+
"verbose_name_plural": "Обложки проектов",
83+
},
84+
),
85+
migrations.RunPython(create_default_project_cover),
86+
migrations.AddField(
87+
model_name="project",
88+
name="cover",
89+
field=models.ForeignKey(
90+
blank=True,
91+
default=projects.models.DefaultProjectCover.get_random_file,
92+
null=True,
93+
on_delete=django.db.models.deletion.SET_DEFAULT,
94+
related_name="project_cover",
95+
to="files.userfile",
96+
),
97+
),
98+
]

projects/models.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,45 @@
1515
User = get_user_model()
1616

1717

18+
class DefaultProjectCover(models.Model):
19+
"""
20+
Default cover model for projects, is chosen randomly at project creation
21+
22+
Attributes:
23+
image: A ForeignKey referencing the image of the cover.
24+
datetime_created: A DateTimeField indicating date of creation.
25+
datetime_updated: A DateTimeField indicating date of update.
26+
"""
27+
28+
image = models.ForeignKey(
29+
UserFile,
30+
on_delete=models.CASCADE,
31+
related_name="default_covers",
32+
null=True,
33+
blank=True,
34+
)
35+
36+
datetime_created = models.DateTimeField(
37+
verbose_name="Дата создания",
38+
null=False,
39+
auto_now_add=True,
40+
)
41+
datetime_updated = models.DateTimeField(
42+
verbose_name="Дата изменения",
43+
null=False,
44+
auto_now=True,
45+
)
46+
47+
@classmethod
48+
def get_random_file(cls):
49+
# FIXME: this is not efficient, but for ~10 default covers it should be ok
50+
return cls.objects.order_by("?").first().image
51+
52+
class Meta:
53+
verbose_name = "Обложка проекта"
54+
verbose_name_plural = "Обложки проектов"
55+
56+
1857
class Project(models.Model):
1958
"""
2059
Project model
@@ -30,6 +69,7 @@ class Project(models.Model):
3069
image_address: A URLField image URL address.
3170
leader: A ForeignKey referring to the User model.
3271
draft: A boolean indicating if Project is a draft.
72+
cover: A ForeignKey referring to the UserFile model, which is the image cover of the project.
3373
datetime_created: A DateTimeField indicating date of creation.
3474
datetime_updated: A DateTimeField indicating date of update.
3575
"""
@@ -58,6 +98,15 @@ class Project(models.Model):
5898

5999
draft = models.BooleanField(blank=False, default=True)
60100

101+
cover = models.ForeignKey(
102+
UserFile,
103+
default=DefaultProjectCover.get_random_file,
104+
on_delete=models.SET_DEFAULT,
105+
related_name="project_cover",
106+
null=True,
107+
blank=True,
108+
)
109+
61110
datetime_created = models.DateTimeField(
62111
verbose_name="Дата создания", null=False, auto_now_add=True
63112
)

projects/serializers.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from core.fields import CustomListField
55
from core.services import get_views_count, get_likes_count, is_fan
6+
from files.serializers import UserFileSerializer
67
from industries.models import Industry
78
from projects.models import Project, Achievement, Collaborator, ProjectNews
89
from projects.validators import validate_project
@@ -63,6 +64,7 @@ class Meta:
6364

6465
class ProjectDetailSerializer(serializers.ModelSerializer):
6566
achievements = AchievementListSerializer(many=True, read_only=True)
67+
cover = UserFileSerializer(required=False)
6668
collaborators = CollaboratorSerializer(
6769
source="collaborator_set", many=True, read_only=True
6870
)
@@ -127,7 +129,8 @@ class Meta:
127129
"datetime_updated",
128130
"views_count",
129131
"likes_count",
130-
"partner_programs_tags",
132+
"cover",
133+
"partner_programs_tags"
131134
]
132135
read_only_fields = [
133136
"leader",

0 commit comments

Comments
 (0)