API теперь возвращает полные URL для медиа-файлов

- Обновлены serializers для автоматической генерации полных URL
- image, attachment и avatar теперь возвращаются с доменом
- Упрощены шаблоны - убрана сложная логика проверки URL
- Используется request.build_absolute_uri() для правильного формирования URL
- Медиа корректно работает на любом домене (локальном и глобальном)
This commit is contained in:
admin i 2025-12-05 09:57:54 +03:00
parent 7fd8e866d2
commit 01d5e5c77e
5 changed files with 41 additions and 43 deletions

View File

@ -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 {}

View File

@ -13,13 +13,7 @@
{% if a %}
{% firstof a.avatar as ava_url %}
{% if ava_url %}
{% if ava_url|slice:":7" == "/media/" %}
<img src="{{ MEDIA_URL_DYNAMIC }}{{ ava_url|slice:"7:" }}" alt="">
{% elif ava_url|slice:":1" == "/" %}
<img src="{{ request.scheme }}://{{ request.get_host }}{{ ava_url }}" alt="">
{% else %}
<img src="{{ ava_url }}" alt="">
{% endif %}
<img src="{{ ava_url }}" alt="" loading="lazy">
{% else %}
<i class="bi-person"></i>
{% endif %}
@ -73,13 +67,7 @@
{% if img_url %}
<div class="feed-img">
{% if post_id %}<a href="#" data-post-link data-post-id="{{ post_id }}" class="stretched-link"></a>{% endif %}
{% if img_url|slice:":7" == "/media/" %}
<img src="{{ MEDIA_URL_DYNAMIC }}{{ img_url|slice:"7:" }}" alt="{{ post.title|default:'Публикация' }}" loading="lazy" decoding="async">
{% elif img_url|slice:":1" == "/" %}
<img src="{{ request.scheme }}://{{ request.get_host }}{{ img_url }}" alt="{{ post.title|default:'Публикация' }}" loading="lazy" decoding="async">
{% else %}
<img src="{{ img_url }}" alt="{{ post.title|default:'Публикация' }}" loading="lazy" decoding="async">
{% endif %}
<img src="{{ img_url }}" alt="{{ post.title|default:'Публикация' }}" loading="lazy" decoding="async">
</div>
{% endif %}
{% endif %}

View File

@ -41,19 +41,7 @@
class="join-ava text-decoration-none"
title="{{ emp_name }}">
{% if ava %}
{% if ava.url %}
{% if ava.url|slice:":7" == "/media/" %}
<img src="{{ MEDIA_URL_DYNAMIC }}{{ ava.url|slice:"7:" }}" alt="">
{% else %}
<img src="{{ ava.url }}" alt="">
{% endif %}
{% else %}
{% if ava|slice:":7" == "/media/" %}
<img src="{{ MEDIA_URL_DYNAMIC }}{{ ava|slice:"7:" }}" alt="">
{% else %}
<img src="{{ ava }}" alt="">
{% endif %}
{% endif %}
<img src="{{ ava.url|default:ava }}" alt="" loading="lazy">
{% else %}
<i class="bi-person" aria-hidden="true"></i>
<span class="visually-hidden">{{ emp_name }}</span>

View File

@ -65,13 +65,7 @@
{% if a %}
{% firstof a.avatar.url a.avatar as ava_url %}
{% if ava_url %}
{% if ava_url|slice:":7" == "/media/" %}
<img src="{{ MEDIA_URL_DYNAMIC }}{{ ava_url|slice:"7:" }}" alt="">
{% elif ava_url|slice:":1" == "/" %}
<img src="{{ request.scheme }}://{{ request.get_host }}{{ ava_url }}" alt="">
{% else %}
<img src="{{ ava_url }}" alt="">
{% endif %}
<img src="{{ ava_url }}" alt="" loading="lazy">
{% else %}
<i class="bi-person"></i>
{% endif %}
@ -118,13 +112,7 @@
{% firstof post.image.url post.image as img_url %}
{% if img_url %}
<div class="feed-img">
{% if img_url|slice:":7" == "/media/" %}
<img src="{{ MEDIA_URL_DYNAMIC }}{{ img_url|slice:"7:" }}" alt="{% firstof post.title 'Публикация' %}">
{% elif img_url|slice:":1" == "/" %}
<img src="{{ request.scheme }}://{{ request.get_host }}{{ img_url }}" alt="{% firstof post.title 'Публикация' %}">
{% else %}
<img src="{{ img_url }}" alt="{% firstof post.title 'Публикация' %}">
{% endif %}
<img src="{{ img_url }}" alt="{% firstof post.title 'Публикация' %}" loading="lazy" decoding="async">
</div>
{% endif %}
{% endif %}