更新个人资料头像 DRF 和 Vue.js
Update profile avatar DRF and Vue.js
我不完全理解为什么我不能在我的 DRF api 中更新图像 url。我将 djoser 用于 api 端点和激活,django rest 框架和 vue.js 用于前端,axios 发出 API 请求。我相信(我可能错了!)我无法使用 FormData() 向 Axios 发出补丁请求,因此通过谷歌搜索我找到了另一种方法,但我仍然收到 HTTP 500 错误和 Django 错误:
Internal Server Error: /api/v1/users/me/
Traceback (most recent call last):
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/rest_framework/viewsets.py", line 125, in view
return self.dispatch(request, *args, **kwargs)
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/rest_framework/views.py", line 509, in dispatch
response = self.handle_exception(exc)
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/rest_framework/views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc)
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
raise exc
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/rest_framework/views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/djoser/views.py", line 175, in me
return self.partial_update(request, *args, **kwargs)
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/rest_framework/mixins.py", line 82, in partial_update
return self.update(request, *args, **kwargs)
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/rest_framework/mixins.py", line 68, in update
self.perform_update(serializer)
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/djoser/views.py", line 149, in perform_update
super().perform_update(serializer)
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/rest_framework/mixins.py", line 78, in perform_update
serializer.save()
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/rest_framework/serializers.py", line 208, in save
assert self.instance is not None, (
AssertionError: `update()` did not return an object instance.
我不确定这是图像文件处理方式的后端问题还是前端提交文件的方式?
这是我的 serializers.py:
class ProfileSerializer(serializers.ModelSerializer):
user = serializers.StringRelatedField(read_only=True)
class Meta:
model = Profile
fields = ("__all__")
class UserSerializer(serializers.ModelSerializer):
profile = ProfileSerializer(required=False, allow_null=True)
class Meta:
model = User
fields = ['username', 'profile', 'password']
extra_kwargs = {"password":{'write_only': True}}
def update(self, instance, validated_data):
parser_classes = (MultiPartParser)
if 'profile' in validated_data:
nested_serializer = self.fields['profile']
nested_instance = instance.profile
nested_data = validated_data.pop('profile')
nested_serializer.update(nested_instance, nested_data)
return super(UserSerializer, self).update(instance, validated_data)
def create(self, validated_data):
return User.objects.create_user(**validated_data)
如您所见,我正在更新嵌套的用户模型以将用户个人资料和用户详细信息放在一起。
Vue.js:
methods: {
updateAvatar() {
const token = localStorage.getItem('token')
const image = this.fileName
const formData = new FormData();
const data = {
profile: {
avatar: image,
},
username: this.user_profile[0]["username"],
password: token
};
console.log("Pre send: ", data);
for(let dataKey in data) {
if(dataKey === 'avatar') {
// append nested object
for (let previewKey in data[dataKey]) {
formData.append(`avatar[${previewKey}]`, data[dataKey][previewKey]);
}
}
else {
formData.append(dataKey, data[dataKey]);
}
}
const base = {
baseURL: 'http://127.0.0.1:8000',
headers: {
"Content-Type": "multipart/form-data"
},
xhrFields: {
withCredentials: true
}
};
const axiosInstance = axios.create(base);
axiosInstance({
url: "/api/v1/users/me/",
data: formData,
method: "patch"
})
// axios
// .patch(`/api/v1/users/me/`, formData)
.then((response) => {
const newArray = response.data;
console.log("Userchanges: ", newArray);
})
.catch((error) => console.log(error.response));
}
},
最后是我的 DRF 用户实例:
尝试取消缩进 update
方法中的 super
调用:
def update(self, instance, validated_data):
parser_classes = (MultiPartParser)
if 'profile' in validated_data:
...
# unindented
return super(UserSerializer, self).update(instance, validated_data)
编辑:
ProfileSerializer
应该可以正常工作,尽管我不确定 nested_serializer = self.fields['profile']
并通过显式 .update()
更新相关实例。尝试将您的代码重写为如下内容:
if 'profile' in validated_data:
nested_instance = instance.profile
nested_data = validated_data.pop('profile')
Profile.objects.filter(pk=nested_instance.pk).update(**nested_data)
如果问题仍然存在,请重新检查来自前端的请求负载。
我不完全理解为什么我不能在我的 DRF api 中更新图像 url。我将 djoser 用于 api 端点和激活,django rest 框架和 vue.js 用于前端,axios 发出 API 请求。我相信(我可能错了!)我无法使用 FormData() 向 Axios 发出补丁请求,因此通过谷歌搜索我找到了另一种方法,但我仍然收到 HTTP 500 错误和 Django 错误:
Internal Server Error: /api/v1/users/me/
Traceback (most recent call last):
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/rest_framework/viewsets.py", line 125, in view
return self.dispatch(request, *args, **kwargs)
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/rest_framework/views.py", line 509, in dispatch
response = self.handle_exception(exc)
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/rest_framework/views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc)
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
raise exc
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/rest_framework/views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/djoser/views.py", line 175, in me
return self.partial_update(request, *args, **kwargs)
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/rest_framework/mixins.py", line 82, in partial_update
return self.update(request, *args, **kwargs)
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/rest_framework/mixins.py", line 68, in update
self.perform_update(serializer)
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/djoser/views.py", line 149, in perform_update
super().perform_update(serializer)
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/rest_framework/mixins.py", line 78, in perform_update
serializer.save()
File "/Users/markmckeon/Django_Stuff/Relate/environment_3_8_8/lib/python3.8/site-packages/rest_framework/serializers.py", line 208, in save
assert self.instance is not None, (
AssertionError: `update()` did not return an object instance.
我不确定这是图像文件处理方式的后端问题还是前端提交文件的方式?
这是我的 serializers.py:
class ProfileSerializer(serializers.ModelSerializer):
user = serializers.StringRelatedField(read_only=True)
class Meta:
model = Profile
fields = ("__all__")
class UserSerializer(serializers.ModelSerializer):
profile = ProfileSerializer(required=False, allow_null=True)
class Meta:
model = User
fields = ['username', 'profile', 'password']
extra_kwargs = {"password":{'write_only': True}}
def update(self, instance, validated_data):
parser_classes = (MultiPartParser)
if 'profile' in validated_data:
nested_serializer = self.fields['profile']
nested_instance = instance.profile
nested_data = validated_data.pop('profile')
nested_serializer.update(nested_instance, nested_data)
return super(UserSerializer, self).update(instance, validated_data)
def create(self, validated_data):
return User.objects.create_user(**validated_data)
如您所见,我正在更新嵌套的用户模型以将用户个人资料和用户详细信息放在一起。
Vue.js:
methods: {
updateAvatar() {
const token = localStorage.getItem('token')
const image = this.fileName
const formData = new FormData();
const data = {
profile: {
avatar: image,
},
username: this.user_profile[0]["username"],
password: token
};
console.log("Pre send: ", data);
for(let dataKey in data) {
if(dataKey === 'avatar') {
// append nested object
for (let previewKey in data[dataKey]) {
formData.append(`avatar[${previewKey}]`, data[dataKey][previewKey]);
}
}
else {
formData.append(dataKey, data[dataKey]);
}
}
const base = {
baseURL: 'http://127.0.0.1:8000',
headers: {
"Content-Type": "multipart/form-data"
},
xhrFields: {
withCredentials: true
}
};
const axiosInstance = axios.create(base);
axiosInstance({
url: "/api/v1/users/me/",
data: formData,
method: "patch"
})
// axios
// .patch(`/api/v1/users/me/`, formData)
.then((response) => {
const newArray = response.data;
console.log("Userchanges: ", newArray);
})
.catch((error) => console.log(error.response));
}
},
最后是我的 DRF 用户实例:
尝试取消缩进 update
方法中的 super
调用:
def update(self, instance, validated_data):
parser_classes = (MultiPartParser)
if 'profile' in validated_data:
...
# unindented
return super(UserSerializer, self).update(instance, validated_data)
编辑:
ProfileSerializer
应该可以正常工作,尽管我不确定 nested_serializer = self.fields['profile']
并通过显式 .update()
更新相关实例。尝试将您的代码重写为如下内容:
if 'profile' in validated_data:
nested_instance = instance.profile
nested_data = validated_data.pop('profile')
Profile.objects.filter(pk=nested_instance.pk).update(**nested_data)
如果问题仍然存在,请重新检查来自前端的请求负载。