'Django default image not saving
I am having an issue while saving a default image whenever I am not uploading an image in ImageField. I can't understand what I am doing wrong, for me it seems everything ok but couldn't find where the bug is.
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)
The view and the saving is just working fine. In fact, the images are saved properly. But when I try to leave the empty field in the image it doesn't provide the image 'default.png' (which I put inside the media folder). Any suggestion?
Solution 1:[1]
Firstly
Make sure you have
default.pngin your media fileIn your view, you are retrieving your image file but it could be null and also your model allows the image to be null, in that case, you have to check if your request file image is null or not.
picture = request.FILES.get('picture', None)
# Allowing null check
# Remove user.student.picture = picture and use the following
if picture:
user.student.picture = picture
Same for your 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()
Solution 2:[2]
I think the misunderstanding is in the "default" value: The default field value is only applied once at the moment of instantiation! Not when the instance is modified or saved.
I try to figure out what happens because some code is missing to be sure:
you instantiate a CustomUser and call the method create_user().
user = CustomUser.objects.create_user(
username=username, password=password, email=email,last_name=last_name, first_name=first_name, user_type=3)
...
...
I suppose in create_user() you also instantiate the Student object ( that is the moment where the default is applied to student.picture!!) and assign it to CustomUser.student
later you assign
...
user.student.picture = picture
but the Student is already instantiated so if here you assign None, it will stay None. The default field value is only applied once at the moment of instantiation.
A solution could be to pass picture to the create_user() call and use it at the instantiation of the Student object.
Another option: only assign the picture if it is not None:
if picture is not None:
user.student.picture = picture
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Khan Asfi Reza |
| Solution 2 |
