|
15 | 15 | from core.services import get_views_count |
16 | 16 | from core.utils import get_user_online_cache_key |
17 | 17 | from files.models import UserFile |
| 18 | +from files.serializers import UserFileSerializer |
18 | 19 | from partner_programs.models import PartnerProgram, PartnerProgramUserProfile |
19 | 20 | from projects.models import Collaborator, Project |
20 | 21 | from projects.validators import validate_project |
|
36 | 37 | from users.validators import specialization_exists_validator |
37 | 38 |
|
38 | 39 |
|
| 40 | +class UserFileReadSerializer(serializers.ModelSerializer): |
| 41 | + class Meta: |
| 42 | + model = UserFile |
| 43 | + fields = ("link", "name", "extension", "mime_type", "size") |
| 44 | + |
| 45 | + |
| 46 | +class FileLinkField(serializers.SlugRelatedField): |
| 47 | + """ |
| 48 | + write-only: принимает link, маппит на UserFile текущего пользователя. |
| 49 | + """ |
| 50 | + |
| 51 | + def get_queryset(self): |
| 52 | + request = self.context.get("request") |
| 53 | + qs = UserFile.objects.all() |
| 54 | + if request and request.user.is_authenticated: |
| 55 | + return qs.filter(user=request.user) |
| 56 | + return qs.none() |
| 57 | + |
| 58 | + |
39 | 59 | class AchievementListSerializer(serializers.ModelSerializer): |
40 | 60 | year = serializers.IntegerField(required=False, allow_null=True) |
41 | | - file_link = serializers.SerializerMethodField() |
| 61 | + files = UserFileSerializer(many=True, read_only=True) |
42 | 62 |
|
43 | 63 | class Meta: |
44 | 64 | model = UserAchievement |
45 | | - fields = ["id", "title", "status", "year", "file_link"] |
| 65 | + fields = ["id", "title", "status", "year", "files"] |
46 | 66 |
|
47 | | - def get_file_link(self, obj): |
48 | | - uaf = obj.files.first() |
49 | | - return uaf.file.link if (uaf and uaf.file) else None |
50 | 67 |
|
| 68 | +class AchievementDetailSerializer(serializers.ModelSerializer): |
| 69 | + files = UserFileSerializer(many=True, read_only=True) |
| 70 | + file_links = FileLinkField( |
| 71 | + slug_field="link", |
| 72 | + many=True, |
| 73 | + write_only=True, |
| 74 | + required=False, |
| 75 | + ) |
51 | 76 |
|
52 | | -class UserFileReadSerializer(serializers.ModelSerializer): |
53 | 77 | class Meta: |
54 | | - model = UserFile |
55 | | - fields = ("link", "name", "extension", "mime_type", "size") |
| 78 | + model = UserAchievement |
| 79 | + fields = [ |
| 80 | + "id", |
| 81 | + "title", |
| 82 | + "status", |
| 83 | + "year", |
| 84 | + "files", |
| 85 | + "file_links", |
| 86 | + ] |
| 87 | + |
| 88 | + @transaction.atomic |
| 89 | + def create(self, validated_data): |
| 90 | + file_objs = validated_data.pop("file_links", []) |
| 91 | + achievement = super().create(validated_data) |
| 92 | + if file_objs: |
| 93 | + achievement.files.set(file_objs) |
| 94 | + return achievement |
| 95 | + |
| 96 | + @transaction.atomic |
| 97 | + def update(self, instance, validated_data): |
| 98 | + file_objs = validated_data.pop("file_links", None) |
| 99 | + achievement = super().update(instance, validated_data) |
| 100 | + if file_objs is not None: |
| 101 | + achievement.files.set(file_objs) |
| 102 | + return achievement |
56 | 103 |
|
57 | 104 |
|
58 | 105 | class AchievementFileReadSerializer(serializers.ModelSerializer): |
@@ -873,66 +920,6 @@ class Meta: |
873 | 920 | ] |
874 | 921 |
|
875 | 922 |
|
876 | | -class AchievementDetailSerializer(serializers.ModelSerializer): |
877 | | - file_link = serializers.URLField(required=False, allow_null=True) |
878 | | - user = serializers.PrimaryKeyRelatedField(read_only=True) |
879 | | - |
880 | | - class Meta: |
881 | | - model = UserAchievement |
882 | | - fields = ["id", "title", "status", "year", "user", "file_link"] |
883 | | - read_only_fields = ["id", "user"] |
884 | | - |
885 | | - def to_representation(self, instance): |
886 | | - data = super().to_representation(instance) |
887 | | - rel = instance.files.first() # UserAchievementFile |
888 | | - data["file_link"] = rel.file.link if (rel and rel.file) else None |
889 | | - return data |
890 | | - |
891 | | - def validate_year(self, value): |
892 | | - import datetime |
893 | | - |
894 | | - if value is None: |
895 | | - return value |
896 | | - cur = datetime.date.today().year |
897 | | - if value < 1900 or value > cur: |
898 | | - raise serializers.ValidationError("Год вне допустимого диапазона.") |
899 | | - return value |
900 | | - |
901 | | - @transaction.atomic |
902 | | - def _set_single_file(self, achievement: UserAchievement, link: str | None): |
903 | | - UserAchievementFile.objects.filter(achievement=achievement).delete() |
904 | | - |
905 | | - if not link: |
906 | | - return |
907 | | - |
908 | | - uf, _ = UserFile.objects.get_or_create(link=link) |
909 | | - |
910 | | - rel = UserAchievementFile(achievement=achievement, file=uf) |
911 | | - rel.clean() |
912 | | - rel.save() |
913 | | - |
914 | | - @transaction.atomic |
915 | | - def create(self, validated_data): |
916 | | - link = validated_data.pop("file_link", None) |
917 | | - achievement = UserAchievement.objects.create(**validated_data) |
918 | | - self._set_single_file(achievement, link) |
919 | | - return achievement |
920 | | - |
921 | | - @transaction.atomic |
922 | | - def update(self, instance, validated_data): |
923 | | - sentinel = object() |
924 | | - link = validated_data.pop("file_link", sentinel) |
925 | | - |
926 | | - for attr, val in validated_data.items(): |
927 | | - setattr(instance, attr, val) |
928 | | - instance.save() |
929 | | - |
930 | | - if link is not sentinel: |
931 | | - self._set_single_file(instance, link) |
932 | | - |
933 | | - return instance |
934 | | - |
935 | | - |
936 | 923 | class EmailSerializer(serializers.Serializer): |
937 | 924 | email = serializers.EmailField() |
938 | 925 |
|
|
0 commit comments