Я пытаюсь обновить профиль пользователя, сделав запрос multipart / form-data put (из моего vue внешнего интерфейса с использованием ax ios), содержащий файл изображения blob в формате png. Я получаю сообщение об ошибке: Расширение файла «» недопустимо. Это поле файла в модели профиля пользователя:
profile_picture = models.FileField(
_("Profile Pictures"),
upload_to="profile_picture",
max_length=100,
blank=True,
null=True,
)
Это сигналы, которые я использую в модели профиля пользователя для сохранить и обновить модель.
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()
Я думаю, что это может быть из-за этих или каких-то других спецификаций c модели Userprofile, которая создает ошибку, потому что на другой модели загрузка файла работает, как задумано, хотя там я делаю сообщение, а не запрос на размещение. Модель Userprofile связана с пользователем с помощью поля «один к одному».
В моем сериализаторе или представлениях нет ничего особенного, что могло бы вызвать ошибку.
Я не знаю, что я мог бы сделать, чтобы исправить это. Спасибо за все советы. Если вам нужна другая информация, не стесняйтесь спрашивать.
Изображение - это данные формы, отправленные с запросом на размещение ... возможно, там что-то не так:
1
Код ax ios, который делает запрос:
import axios from 'axios'
const apiClient = axios.create({
baseURL: `http://127.0.0.1:8000/`,
withCredentials: false,
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data'
}
})
export default {
updateUser(pk, params) {
return apiClient.put('/users/' + pk + '/', params)
}
}
Это та часть, где я кадрирую изображение, и это dataURI, который затем конвертирую в blob для отправки внутренний сервер:
methods: {
crop() {
const { coordinates, canvas } = this.$refs.cropper.getResult()
this.coordinates = coordinates
this.file = canvas.toDataURL()
},
uploadImage(event) {
const input = event.target
if (input.files && input.files[0]) {
// create a new FileReader to read this image and convert to base64 format
const reader = new FileReader()
// Define a callback function to run, when FileReader finishes its job
reader.onload = (e) => {
// Read image as base64 and set to imageData
this.file = e.target.result
}
// Start the reader job - read file as a data url (base64 format)
reader.readAsDataURL(input.files[0])
}
},
dataURItoBlob(dataURI) {
// convert base64 to raw binary data held in a string
const byteString = atob(dataURI.split(',')[1])
// separate out the mime component
const mimeString = dataURI
.split(',')[0]
.split(':')[1]
.split(';')[0]
// write the bytes of the string to an ArrayBuffer
const ab = new ArrayBuffer(byteString.length)
const ia = new Uint8Array(ab)
for (let i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i)
}
return new Blob([ab], { type: mimeString })
},
async updateUser() {
this.crop()
delete this.user.password2
const formData = new FormData()
if (this.file)
formData.append('profile_picture', this.dataURItoBlob(this.file))
if (this.user.username) formData.append('username', this.user.username)
else formData.append('username', this.$auth.user.username)
if (this.user.email) formData.append('email', this.user.email)
if (this.user.bio) formData.append('bio', this.user.bio)
if (this.user.password) formData.append('password', this.user.password)
else formData.append('password', this.$auth.user.password)
await UserFormService.updateUser(this.$auth.user.pk, formData)
await this.$store.dispatch('users/updateUser', this.user)
this.$auth.setUser(this.$store.state.users.user)
this.$router.push('/users/me')