Изображение по умолчанию в Django не сохраняется
У меня проблема с сохранением изображения по умолчанию, когда я не загружаю изображение в ImageField. Я не могу понять, что я делаю неправильно, для меня вроде бы все в порядке, но я не могу найти, где ошибка.
models.py
class Student(models.Model):
user = models.OneToOneField(CustomUser, on_delete=models.CASCADE)
date_of_birth = models.DateField()
fiscal_code = models.CharField(max_length=50)
phone = models.CharField(max_length=50)
license = models.ForeignKey(
License, on_delete=models.CASCADE, blank=True, null=True)
picture = models.ImageField(
blank=True, null=True, default='default.png')
id_card = models.ForeignKey(
IDCard, on_delete=models.CASCADE, blank=True, null=True)
address = models.CharField(max_length=100)
cap = models.CharField(max_length=10)
city = models.CharField(max_length=100)
province = models.CharField(max_length=100)
country = models.CharField(max_length=100)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
views.py
def create_student(request):
context = {
}
if request.method == 'POST':
username = request.POST.get('username')
first_name = request.POST.get('first_name')
last_name = request.POST.get('last_name')
date_of_birth = request.POST.get('date_of_birth')
email = request.POST.get('email')
phone = request.POST.get('phone')
password = request.POST.get('password')
address = request.POST.get('address')
cap = request.POST.get('cap')
province = request.POST.get('province')
country = request.POST.get('country')
fiscal_code = request.POST.get('fiscal_code')
id_number = request.POST.get('id_number')
expire_date = request.POST.get('expire_date')
picture = request.FILES.get('picture')
id_image = request.FILES.get('id_image')
# fs = FileSystemStorage()
# filename = fs.save(picture.name, picture)
# profile_pic_url = fs.url(filename)
# filename2 = fs.save(id_image.name, id_image)
# id_image_url = fs.url(filename2)
try:
user = CustomUser.objects.create_user(
username=username, password=password, email=email, last_name=last_name, first_name=first_name, user_type=3)
user.student.address = address
user.student.date_of_birth = date_of_birth
user.student.cap = cap
user.student.province = province
user.student.country = country
user.student.phone = phone
user.student.fiscal_code = fiscal_code
user.student.picture = picture
user.save()
id_card = IDCard.objects.create(
number=id_number, expire_date=expire_date, picture=id_image)
id_card.save()
messages.success(request, "Successfully Added Student")
return HttpResponseRedirect(reverse('user:student_list'))
except:
messages.error(request, "Failed to Add Student")
return HttpResponseRedirect(reverse('user:create_student'))
return render(request, 'user/create_student.html', context)
settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = [
BASE_DIR / 'static',
]
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
urls.py
urlpatterns = [
path('', include('user.urls')),
path('admin/', admin.site.urls),
path('student/', include('student.urls')),
path('instructor/', include('instructor.urls')),
]
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
<
Вы сохраняете только User объект, а не Student один.
views.py:
...
user.student.picture = picture
user.save()
user.student.save() # this will save student object to databse
id_card = IDCard.objects.create(
number=id_number, expire_date=expire_date, picture=id_image)
id_card.save() # this line does nothing, because object is saved in create() function
...
Другое дело, что вам, вероятно, не следует позволять Django сохранять изображение как None.
models.py:
class Student(models.Model):
...
picture = models.ImageField(
blank=True, null=False, default='default.png')
...
Первоначально
Убедитесь, что в вашем медиафайле есть
default.pngВ вашем представлении вы получаете файл изображения, но он может быть нулевым, а также ваша модель позволяет изображению быть нулевым, в этом случае вы должны проверить, является ли изображение файла запроса нулевым или нет.
picture = request.FILES.get('picture', None)
# Allowing null check
# Remove user.student.picture = picture and use the following
if picture:
user.student.picture = picture
То же самое для вашего id_image
id_image = request.FILES.get('id_image', None)
#...
# I assume id_image will also use default
id_card = IDCard(number=id_number, expire_date=expire_date, )
if id_image:
id_card.picture=id_image
id_card.save()
Я думаю, что недоразумение заключается в значении "по умолчанию": Значение поля по умолчанию применяется только один раз в момент инстанцирования! Не тогда, когда экземпляр изменяется или сохраняется.
Я пытаюсь понять, что происходит, потому что некоторый код отсутствует, чтобы быть уверенным:
вы создаете CustomUser и вызываете метод create_user().
user = CustomUser.objects.create_user(
username=username, password=password, email=email,last_name=last_name, first_name=first_name, user_type=3)
...
...
Полагаю, что в create_user() вы также инстанцируете объект Student (именно в этот момент по умолчанию применяется student.picture!!!) и присваиваете его CustomUser.student
позже вы назначаете
...
user.student.picture = picture
но Student уже инстанцирован, поэтому если здесь присвоить None, то оно останется None. Значение поля по умолчанию применяется только один раз в момент инстанцирования.
Решением может быть передача картинки в вызов create_user() и использование ее при инстанцировании объекта Student.
Другой вариант: назначать картинку, только если она не None:
if picture is not None:
user.student.picture = picture