我想知道我的Django后端应该使用哪一种方法来更改用户配置文件图片的表示形式/用户配置文件图片的路径。
因为我有一个默认图像'/media/ default _l.png‘,它在我的模型中使用,如下所示:
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,如下所示:
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)
上传图像的序列化程序是
# 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)上传工作良好的与视图
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)但是当我请求用户数据时,默认图像的图像路径将被返回!
{
"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 ),我希望显示上传的用户化身。
我使用这个序列化程序显示用户的数据:
# 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配置:
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' 我在用
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.0FYI:
我已经测试过的是这种方法
# 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',因为我不想修复路径,而是显示实际的化身路径,所以我没有修复这个问题。
如果有人能帮我,我会很高兴的!
get_avatar_url是将代码放入的正确位置吗?提前感谢!
发布于 2020-10-25 10:33:25
我很高兴我找到了我丢失的那件东西!
我已经将序列化程序重构为
# 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上传图片给不同的用户时,我发现我只是在更改超级用户的化身,而不是应该更改的登录自定义用户。我使用的是自定义用户模型,因此需要使用
user = models.ForeignKey(settings.AUTH_USER_MODEL)当引用自定义用户->时,它是在文档中描述!
这是关键!,因为现在ImageField“化身”的正确路径是由序列化程序提供的!
"avatar": "/media/user_avatar/user_2.png"所以我已经解决了:)!
https://stackoverflow.com/questions/64413765
复制相似问题