首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DRF显示默认图像,即使用户上传了图像

DRF显示默认图像,即使用户上传了图像
EN

Stack Overflow用户
提问于 2020-10-18 13:13:51
回答 1查看 367关注 0票数 0

我想知道我的Django后端应该使用哪一种方法来更改用户配置文件图片的表示形式/用户配置文件图片的路径。

因为我有一个默认图像'/media/ default _l.png‘,它在我的模型中使用,如下所示:

代码语言:javascript
复制
class User(AbstractBaseUser,PermissionsMixin):
    id = models.AutoField(primary_key=True)  # custom User models must have an integer 
    avatar = models.ImageField(upload_to=avatar_upload, blank=True, default='default_l.png', validators=[validators.FileExtensionValidator(['jpg','jpeg', 'gif', 'png',])])
...

该默认图像用于显示图像,只要用户没有上传他选择的配置文件图像。

当用户上传图像时,他会将图像上传到upload_to=avatar_upload,如下所示:

代码语言:javascript
复制
def avatar_upload(instance, filename): #https://c14l.com/blog/django-image-upload-to-dynamic-path.html
        #return os.path.join('images/user_avatar/', 'user_{0}', '{1}').format(instance.user.id, filename)
        new_filename = '{}_{}.{}'.format('user',instance.pk, 'png')
        return "user_avatar/{}".format(new_filename)

所以默认的图像是/media/default_l.png

上传的图像是/media/user_avatar/user_3.png (= user_pk.png)

上传图像的序列化程序是

代码语言:javascript
复制
# Upload User Profile Picture
class AvatarSerializer(serializers.ModelSerializer):
    avatar = serializers.ImageField(max_length=None, use_url=True) 

    class Meta:
        model = User
        fields = ['avatar']

    def save(self, *args, **kwargs):
        if self.instance.avatar:
            #delete if not default
            if "/media/default_l.png" not in self.instance.avatar.url:
                self.instance.avatar.delete()
        return super().save(*args, **kwargs)

上传工作良好的与视图

代码语言:javascript
复制
class UserUploadImage(RetrieveUpdateAPIView):
    #permission_classes = (IsLoggedInUser, )
    parser_class = [MultiPartParser, FormParser]
    serializer_class = AvatarSerializer
    queryset = User.objects.all()

    def post(self, request, pk, format=None):
        user = User.objects.get(id=pk)

        if not user.is_authenticated:
            return HttpResponse('Unauthorized', status=401)
            
        serializer = AvatarSerializer(data= request.data, instance=request.user)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status.HTTP_200_OK)
        else:
            return Response(serializer.errors, status.HTTP_400_BAD_REQUEST)

但是当我请求用户数据时,默认图像的图像路径将被返回!

  • 这条路错了!
代码语言:javascript
复制
    {
        "id": 1,
        "username": "foo",
        "email": "foo@test.com",
        "description": null,
        "avatar": "/media/media/default_l.png",
        "token": .....
    }

如您所见,即使在媒体中没有" media“文件夹,api也返回”/media/media/defaultl.png“!我还没弄清楚额外的“媒体”是从哪里来的.,但我不想修复路径中的2x媒体。如果有"/media/ user _ avatar /“文件夹(例如,称为"user_3.png”,其中"3“是用户的pk ),我希望显示上传的用户化身。

我使用这个序列化程序显示用户的数据:

代码语言:javascript
复制
# Load user profile
class UserProfileSerializer(serializers.ModelSerializer):
    token = serializers.SerializerMethodField('get_tokens_for_user')

    class Meta:
        model = User
        fields = ('username', 'email', 'description', 'avatar', 'token', )
    
    #https://github.com/davesque/django-rest-framework-simplejwt
    def get_tokens_for_user(self, user):
        refresh = RefreshToken.for_user(user)

        return {
            'refresh': str(refresh),
            'access': str(refresh.access_token),
        } 

要完成我的数据,下面是相关的settings.py配置:

代码语言:javascript
复制
MEDIA_ROOT = os.path.join(BASE_DIR,'media')
MEDIA_URL = '/media/'

#location where django collect all static files
STATIC_ROOT = os.path.join(BASE_DIR,'static')# location where you will store your static files
STATICFILES_DIRS = [os.path.join(BASE_DIR,'myProject/static')]
STATIC_URL = '/static/'

AUTH_USER_MODEL = 'posts.User' 

我在用

代码语言:javascript
复制
Django==2.2.9
django-cors-headers==2.4.0
django-rest-auth==0.9.5
django-sslserver==0.20
djangorestframework==3.9.1
djangorestframework-simplejwt==4.3.0

FYI:

我已经测试过的是这种方法

代码语言:javascript
复制
# Load user profile
class UserProfileSerializer(serializers.ModelSerializer):
    #HyperlinkSerializer for UserAvatar
    #userimage = serializers.ImageField()
    #dogimage = serializers.ImageField()
    puppy = serializers.StringRelatedField(many=True)
    friendnames = serializers.StringRelatedField(many=True, source='from_user')#FriendSerializer as Link
    token = serializers.SerializerMethodField('get_tokens_for_user')
    avatar_url = serializers.SerializerMethodField()


    class Meta:
        model = User
        fields = ('username', 'email', 'description', 'friendnames', 'puppy', 'last_login', 'created_at','birthday', 'email_confirmed', 'is_premium', 'avatar','avatar_url', 'walkstatus', 'leine', 'token', )
    
    #https://github.com/davesque/django-rest-framework-simplejwt
    def get_tokens_for_user(self, user):
        refresh = RefreshToken.for_user(user)

        return {
            'refresh': str(refresh),
            'access': str(refresh.access_token),
        } 


    def get_avatar_url(self, obj):
        request = self.context.get('request')
        return request.build_absolute_uri(obj.avatar.url)

假设实现我的需求的正确位置是get_avatar_url方法。

但是我收到了'NoneType' object has no attribute 'build_absolute_uri',因为我不想修复路径,而是显示实际的化身路径,所以我没有修复这个问题。

如果有人能帮我,我会很高兴的!

  • 如何检查当前用户在"/media/ user _avatar“文件夹中是否有一个名为"user_.png”的图像,并显示它的abolute路径而不是化身的默认图像路径?
  • get_avatar_url是将代码放入的正确位置吗?

提前感谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-10-25 10:33:25

我很高兴我找到了我丢失的那件东西!

我已经将序列化程序重构为

代码语言:javascript
复制
# Load user profile
class UserProfileSerializer(serializers.ModelSerializer):

    puppy = serializers.StringRelatedField(many=True)
    friendnames = serializers.StringRelatedField(many=True, source='from_user')#FriendSerializer as Link
    token = serializers.SerializerMethodField('get_tokens_for_user')
    avatar = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = ('puppies', 'friendnames', 'token', 'avatar' )
    
    def get_tokens_for_user(self, user):
        refresh = RefreshToken.for_user(user)

        return {
            'refresh': str(refresh),
            'access': str(refresh.access_token),
        } 


    def get_avatar(self, obj):
        request = self.context.get('request')
        return request.build_absolute_uri(obj.avatar.url)

当我用已知的bug上传图片给不同的用户时,我发现我只是在更改超级用户的化身,而不是应该更改的登录自定义用户。我使用的是自定义用户模型,因此需要使用

代码语言:javascript
复制
user = models.ForeignKey(settings.AUTH_USER_MODEL)

当引用自定义用户->时,它是在文档中描述

这是关键!,因为现在ImageField“化身”的正确路径是由序列化程序提供的!

代码语言:javascript
复制
    "avatar": "/media/user_avatar/user_2.png"

所以我已经解决了:)!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64413765

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档