#django #django-rest-framework
#django #django-rest-framework
Вопрос:
Я очень устал от поиска решения, чтобы сделать поле изображения необязательным в API django rest framework. Я перепробовал все решения, которые я нашел в stack overflow, но, похоже, ничего не работает нормально. Я знаю, что есть меньше сообщений, связанных с одним и тем же запросом, но я не нашел решения в этом.
Позвольте мне объяснить вам, каковы мои требования. Вот моя пользовательская модель с некоторыми основными информационными полями, включая поле изображения.
models.py
class User(models.Model):
firstname = models.CharField(max_length=100, validators=[firstname_check])
lastname = models.CharField(max_length=100, blank=True, null=True, validators=[lastname_check])
username = models.CharField(max_length=100, unique=True, blank=True, null=True, validators=[username_check])
email = models.EmailField(max_length=100, unique=True)
password = models.CharField(max_length=50, blank=True, null=True, validators=[password_check])
mobnum = models.CharField(max_length=50, blank=True, null=True, validators=[mobile_num_len])
timestamp = models.DateTimeField(auto_now=True)
gender = models.CharField(max_length=50, blank=True, null=True)
language = models.CharField(max_length=100, blank=True, null=True)
profile_img = models.ImageField(upload_to ='uploads/', blank=True, null=True)
is_active = models.BooleanField(default=False, blank=True, null=True)
serializer.py
from utils import Base64ImageField
class UserMannualSerializer(serializers.ModelSerializer):
profile_img = Base64ImageField(
max_length=None, use_url=True, allow_empty_file=True, required=False
)
class Meta:
model = User
fields = [
'firstname',
'lastname',
'username',
'email',
'password',
'mobnum',
'gender',
'language',
'timestamp'
'profile_img'
]
Вот функция Base64ImageField (), которую я написал внутри utils.py досье. Который примет строку base64, преобразует ее обратно и сохранит на сервере, и это происходит правильно. Но когда я не загружаю изображение, оно выдает ошибку. Если я передам атрибуты (allow_empty_file=True, required= False) и их значения в Base64ImageField(), даже если это вообще не сработает.
utils.py
class Base64ImageField(serializers.ImageField):
"""
A Django REST framework field for handling image-uploads through raw post data.
It uses base64 for encoding and decoding the contents of the file.
Heavily based on
https://github.com/tomchristie/django-rest-framework/pull/1268
Updated for Django REST framework 3.
"""
def to_internal_value(self, data):
# Check if this is a base64 string
if isinstance(data, six.string_types):
# Check if the base64 string is in the "data:" format
if 'data:' in data and ';base64,' in data:
# Break out the header from the base64 content
header, data = data.split(';base64,')
# Try to decode the file. Return validation error if it fails.
try:
decoded_file = base64.b64decode(data)
except TypeError:
self.fail('invalid_image')
# Generate file name:
file_name = str(uuid.uuid4())[:12] # 12 characters are more than enough.
# Get the file name extension:
file_extension = self.get_file_extension(file_name, decoded_file)
complete_file_name = "%s.%s" % (file_name, file_extension, )
data = ContentFile(decoded_file, name=complete_file_name)
return super(Base64ImageField, self).to_internal_value(data)
def get_file_extension(self, file_name, decoded_file):
import imghdr
extension = imghdr.what(file_name, decoded_file)
extension = "jpg" if extension == "jpeg" else extension
return extension
Note: If I give default field in the ImageField, then also it’s not working. It’s not taking the default image if I don’t upload one.
I’m working with Python 3.6, Django 3.1.1, djangorestframework 3.11.1
Please let me know if someone has already been faced this problem and got the solution or any alternative would also help. I would appreciate your help. Thank you.
Edited part
Here is the code from another app, how I’m sending the code from the other django app.
def register_confirm(request):
"""
getting the sign-up required values
dumping the all the parameters as json
using requests library to achieve the register via API
passing the success response to profile.html
"""
std_mobnum = ''
if request.method == "POST":
firstname = request.POST.get("fname")
lastname = request.POST.get("lname")
username = request.POST.get("uname")
email = request.POST.get("email")
password = request.POST.get("pswd")
mobnum = request.POST.get("mobnum")
image = request.POST.get('imagtobase64')
gender = request.POST.get("gender")
language = request.POST.get("language")
params={
'firstname':firstname,
'lastname':lastname,
'username':username,
'email':email,
'password':password,
'mobnum':mobnum,
'profile_img':image,
'gender':gender,
'language':language,
}
print(params)
headers = {'content-type':'application/json'}
response = requests.post("http://127.0.0.1:8000/user-create/", data=json.dumps(params), headers=headers)
user_data = response.json()
print(user_data)
return JsonResponse(user_data)
Примечание: я отправляю строку base64 изображения с помощью jquery в Api.
Это код views.py файл, в котором я обрабатываю запрос сериализатора и post.
views.py
api_view(['POST'])
@parser_classes([MultipartJsonParser, FormParser, JsonParser])
def userCreate(запрос):
status=''
message = ''
data ={}
try:
mannualSerializer = UserMannualSerializer(data = request.data)
print("serializer started")
if mannualSerializer.is_valid():
print("form validated")
mannualSerializer.save()
print("saved")
status='success'
message = 'User created successfully.'
data= mannualSerializer.data
except Exception as error:
status='failure'
message = error
response = {
"status":status,
"message":message,
"data":data
}
return Response(response)
Комментарии:
1. настройки
required=False
будут выполнять эту работу в обычном режиме. Какая ошибка у вас есть? Можете ли вы показать отправленную вами полезную нагрузку?2. На самом деле, он не передает serializers.valid() и выдает ошибку: {‘status’: ‘сбой’, ‘message’: {‘profile_img’: [‘Отправленный файл пуст.’]}, ‘data’: {}}.
3. Есть ли у вашей полезной нагрузки
profile_img
поле? Создайте полезную нагрузку, в которой нетprofile_img
поля, и повторите попытку4. Вы не должны включать это поле в полезную нагрузку. Если вы включаете, DRF считает, что с полем связаны какие-то данные, и получает проверку и, следовательно, ошибку. Итак, опустите это поле, если вы не отправляете изображение (я чертовски уверен, что это возможно).
5. Привет, @Arakkal Abu. Большое вам спасибо. Ранее я был немного смущен вашим последним ответом. Теперь я понял. Итак, теперь, как вы сказали, если есть изображение, я могу добавить атрибут profile_image к полезной нагрузке, иначе я не буду добавлять этот атрибут, и теперь это дает мне результат, как и ожидалось. Я ценю ваше время.