简体   繁体   English

从 F() function 解析 Django/DRF ImageField URL

[英]Resolve Django/DRF ImageField URL from F() function

I have a use case where I'm attempting to override an Image URL if it exists in our database.我有一个用例,如果图像 URL 存在于我们的数据库中,我会尝试覆盖它。

Here is the section of the queryset that is grabbing the ImageField from via an F() query.这是通过F()查询获取ImageField的查询集部分。

preferred_profile_photo=Case(
            When(
                # agent not exists
                Q(agent__id__isnull=False),
                then=F("agent__profile__profile_photo"),
            ),
            default=Value(None, output_field=ImageField()),
        )

The Case-When is resolving correctly, but the issue is the value returns from F("agent__profile__profile_photo") is not the URL than can be used by the UI. Case-When 可以正确解决,但问题是从F("agent__profile__profile_photo")返回的值不是 UI 可以使用的 URL。 Instead it is something like: "agentphoto/09bd7dc0-62f6-49ab-blah-6c57b23029d7/profile/1665342685--77e51d9c5asdf345364f774d0b2def48.jpeg"相反,它类似于: "agentphoto/09bd7dc0-62f6-49ab-blah-6c57b23029d7/profile/1665342685--77e51d9c5asdf345364f774d0b2def48.jpeg"

Typically, I'd retrieve the URL via agent.profile.profile_photo.url , but I receive the following when attempting to perform preferred_profile_photo.url : AttributeError: 'str' object has no attribute 'url' . Typically, I'd retrieve the URL via agent.profile.profile_photo.url , but I receive the following when attempting to perform preferred_profile_photo.url : AttributeError: 'str' object has no attribute 'url' .

I've tried wrapping in Value(..., output_field=ImageField()) with no luck.我试过包装Value(..., output_field=ImageField())没有运气。

The crux here is retrieving the url from the ImageField after resolving from F()这里的关键是从 F() 解析后从 ImageField 中检索 url

For reference, I'm using storages.backends.s3boto3.S3Boto3Storage .作为参考,我正在使用storages.backends.s3boto3.S3Boto3Storage

Appreciate any help!感谢任何帮助!

I was able to implement this using some information from this post .我能够使用这篇文章中的一些信息来实现这一点。

Here is the helper function I used to implement:这是我用来实现的助手function:

from django.core.files.storage import get_storage_class
def get_media_storage_url(file_name: str) -> str:
    """Takes the postgres stored ImageField value and converts it to
    the proper S3 backend URL. For use cases, where calling .url on the
    photo field is not feasible.

    Args:
        file_name (str): the value of the ImageField

    Returns:
        str: the full URL of the object usable by the UI
    """
    media_storage = get_storage_class()()
    return media_storage.url(name=file_name)

Django doesn't store full URL in DB. Django 不会在 DB 中存储完整的 URL。 It builds absolute url on code level.它在代码级别构建绝对 url。 Quote from docs :引用自文档

All that will be stored in your database is a path to the file (relative to MEDIA_ROOT).将存储在数据库中的所有内容都是文件的路径(相对于 MEDIA_ROOT)。

You can use build_absolute_uri() method to get full URL of your files.您可以使用build_absolute_uri()方法获取文件的完整 URL。 For example you can do it on serializer level:例如,您可以在序列化程序级别执行此操作:

class YourSerializer(ModelSerializer):
    preferred_profile_photo = serializers.SerializerMethodField()

    class Meta:
        model = YourModel
        fields = [
            'preferred_profile_photo',
        ]

    def get_preferred_profile_photo(self, obj):
        request = self.context.get('request')
        return request.build_absolute_uri(obj.preferred_profile_photo)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM