From 01d5e5c77e58ca86ff0bed96b05746c692f3ec2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=B3=D0=BE=D1=80=D1=8C=20=D0=9D=D0=B0=D0=B4=D0=B5?= =?UTF-8?q?=D0=B8=D0=BD?= Date: Fri, 5 Dec 2025 09:57:54 +0300 Subject: [PATCH] =?UTF-8?q?API=20=D1=82=D0=B5=D0=BF=D0=B5=D1=80=D1=8C=20?= =?UTF-8?q?=D0=B2=D0=BE=D0=B7=D0=B2=D1=80=D0=B0=D1=89=D0=B0=D0=B5=D1=82=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=BB=D0=BD=D1=8B=D0=B5=20URL=20=D0=B4=D0=BB=D1=8F?= =?UTF-8?q?=20=D0=BC=D0=B5=D0=B4=D0=B8=D0=B0-=D1=84=D0=B0=D0=B9=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Обновлены serializers для автоматической генерации полных URL - image, attachment и avatar теперь возвращаются с доменом - Упрощены шаблоны - убрана сложная логика проверки URL - Используется request.build_absolute_uri() для правильного формирования URL - Медиа корректно работает на любом домене (локальном и глобальном) --- backend/api/v1/feed/serializers.py | 38 ++++++++++++++++++-- backend/static/js/components/feedRenderer.js | 0 backend/templates/feed/_feed_cards.html | 16 ++------- backend/templates/feed/feed_list.html | 14 +------- backend/templates/feed/post_detail.html | 16 ++------- 5 files changed, 41 insertions(+), 43 deletions(-) create mode 100644 backend/static/js/components/feedRenderer.js diff --git a/backend/api/v1/feed/serializers.py b/backend/api/v1/feed/serializers.py index 68e93495..383638d6 100644 --- a/backend/api/v1/feed/serializers.py +++ b/backend/api/v1/feed/serializers.py @@ -8,14 +8,13 @@ from rest_framework import serializers from feed.constants import TYPE_COMPANY, TYPE_DEPARTMENT, TYPE_EMPLOYEE from feed.models import Comment, Post, PostLike -from ..serializers import Base64ImageField Employee = get_user_model() class AuthorMiniSerializer(serializers.ModelSerializer): full_name = serializers.SerializerMethodField() - avatar = Base64ImageField(read_only=True) + avatar = serializers.SerializerMethodField() class Meta: model = Employee @@ -26,6 +25,17 @@ class AuthorMiniSerializer(serializers.ModelSerializer): ln = (obj.last_name or "").strip() nm = f"{fn} {ln}".strip() return nm + + def get_avatar(self, obj): + """Возвращает полный URL для аватара""" + if not obj.avatar: + return None + request = self.context.get('request') + if request and hasattr(obj.avatar, 'url'): + return request.build_absolute_uri(obj.avatar.url) + if hasattr(obj.avatar, 'url'): + return obj.avatar.url + return str(obj.avatar) class CommentMiniSerializer(serializers.ModelSerializer): @@ -54,6 +64,10 @@ class PostListSerializer(serializers.ModelSerializer): # для ссылок на отдел department_id = serializers.IntegerField(read_only=True) last_comment = serializers.SerializerMethodField() + + # Переопределяем поля для полных URL + image = serializers.SerializerMethodField() + attachment = serializers.SerializerMethodField() class Meta: model = Post @@ -88,6 +102,26 @@ class PostListSerializer(serializers.ModelSerializer): "is_liked", ) + def get_image(self, obj): + """Возвращает полный URL для изображения""" + if not obj.image: + return None + request = self.context.get('request') + if request and hasattr(obj.image, 'url'): + return request.build_absolute_uri(obj.image.url) + return obj.image.url if hasattr(obj.image, 'url') else str(obj.image) + + def get_attachment(self, obj): + """Возвращает полный URL для вложения""" + if not obj.attachment: + return None + request = self.context.get('request') + if request and hasattr(obj.attachment, 'url'): + return request.build_absolute_uri(obj.attachment.url) + if hasattr(obj.attachment, 'url'): + return obj.attachment.url + return str(obj.attachment) + def get_last_comment(self, obj): # Берём готовую мапу из контекста, собранную во viewset.list() lc_map = self.context.get("last_comments_map") or {} diff --git a/backend/static/js/components/feedRenderer.js b/backend/static/js/components/feedRenderer.js new file mode 100644 index 00000000..e69de29b diff --git a/backend/templates/feed/_feed_cards.html b/backend/templates/feed/_feed_cards.html index 33abc1f1..f9b600e2 100644 --- a/backend/templates/feed/_feed_cards.html +++ b/backend/templates/feed/_feed_cards.html @@ -13,13 +13,7 @@ {% if a %} {% firstof a.avatar as ava_url %} {% if ava_url %} - {% if ava_url|slice:":7" == "/media/" %} - - {% elif ava_url|slice:":1" == "/" %} - - {% else %} - - {% endif %} + {% else %} {% endif %} @@ -73,13 +67,7 @@ {% if img_url %}
{% if post_id %}{% endif %} - {% if img_url|slice:":7" == "/media/" %} - {{ post.title|default:'Публикация' }} - {% elif img_url|slice:":1" == "/" %} - {{ post.title|default:'Публикация' }} - {% else %} - {{ post.title|default:'Публикация' }} - {% endif %} + {{ post.title|default:'Публикация' }}
{% endif %} {% endif %} diff --git a/backend/templates/feed/feed_list.html b/backend/templates/feed/feed_list.html index 093b2a68..fe91e1b7 100644 --- a/backend/templates/feed/feed_list.html +++ b/backend/templates/feed/feed_list.html @@ -41,19 +41,7 @@ class="join-ava text-decoration-none" title="{{ emp_name }}"> {% if ava %} - {% if ava.url %} - {% if ava.url|slice:":7" == "/media/" %} - - {% else %} - - {% endif %} - {% else %} - {% if ava|slice:":7" == "/media/" %} - - {% else %} - - {% endif %} - {% endif %} + {% else %} {{ emp_name }} diff --git a/backend/templates/feed/post_detail.html b/backend/templates/feed/post_detail.html index 5b297372..12801518 100644 --- a/backend/templates/feed/post_detail.html +++ b/backend/templates/feed/post_detail.html @@ -65,13 +65,7 @@ {% if a %} {% firstof a.avatar.url a.avatar as ava_url %} {% if ava_url %} - {% if ava_url|slice:":7" == "/media/" %} - - {% elif ava_url|slice:":1" == "/" %} - - {% else %} - - {% endif %} + {% else %} {% endif %} @@ -118,13 +112,7 @@ {% firstof post.image.url post.image as img_url %} {% if img_url %}
- {% if img_url|slice:":7" == "/media/" %} - {% firstof post.title 'Публикация' %} - {% elif img_url|slice:":1" == "/" %} - {% firstof post.title 'Публикация' %} - {% else %} - {% firstof post.title 'Публикация' %} - {% endif %} + {% firstof post.title 'Публикация' %}
{% endif %} {% endif %}