Home > Software engineering >  Django unable to upload image using multipart/form-data
Django unable to upload image using multipart/form-data

Time:08-24

I am trying to upload a profile image for my user model on user registration, but the image is not getting saved at the media folder, and the default image is displayed. (When I edit the user's image in django admin, it gets saved). Where am I causing this problem, and how to fix it?

My register function in views.py:

def register(request):
if request.method != 'POST':
    form = UserCreationForm()
else:
    form = UserCreationForm(request.POST)
    if form.is_valid():
        form.save()
        return redirect('account:login')

context = {'form': form}

return render(request, 'account/register.html', context)

My register.html file:

{% extends 'base.html' %} {% block contents %}
<h1>Register</h1>

<form method="post" enctype="multipart/form-data">
{% csrf_token %} {{form.as_p}}

<input type="submit" name="Create User" />
</form>
{% endblock %}

My user creation form:

class UserCreationForm(forms.ModelForm):
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(
    label='Password confirmation', widget=forms.PasswordInput)

class Meta:
    model = User
    fields = ('email', 'username', 'date_of_birth', 'profile_image')

def clean_password2(self):
    password1 = self.cleaned_data.get("password1")
    password2 = self.cleaned_data.get("password2")
    if password1 and password2 and password1 != password2:
        raise forms.ValidationError("Passwords don't match")
    return password2

def save(self, commit=True):
    user = super().save(commit=False)
    user.set_password(self.cleaned_data["password1"])
    if commit:
        user.save()
    return user

and my User model:

class UserManager(BaseUserManager):
def create_user(self, email, username, date_of_birth, password, profile_image):

    if not email:
        raise ValueError('Users must have an email address')

    user = self.model(
        email=self.normalize_email(email),
        username = username,
        date_of_birth= date_of_birth,
        profile_image = profile_image,
    )

    user.set_password(password)
    user.save(using=self._db)
    return user

class User(AbstractBaseUser):
email = models.EmailField(
    verbose_name='email',
    max_length=255,
    unique=True,
)
username = models.CharField(max_length=20, unique=True)
date_of_birth = models.DateField()
profile_image = models.ImageField(upload_to='profile_pic', default='/profile_pic/default.jpg')

is_active = models.BooleanField(default=True) 
is_admin = models.BooleanField(default=False)

objects = UserManager()

USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email', 'date_of_birth']

CodePudding user response:

Uploaded file data is found in request.FILES, you need to pass this to your form along with the POST data when handling file uploads

form = UserCreationForm(request.POST, request.FILES)

CodePudding user response:

A view handling this form will receive the file data in request.FILES, which is a dictionary containing a key for each FileField (or ImageField, or other FileField subclass) in the form. So the data from the above form would be accessible as request.FILES['file'].

Official Example -

def upload_file(request):
    if request.method == 'POST':
        form = UploadFileForm(request.POST, request.FILES)
        if form.is_valid():
            handle_uploaded_file(request.FILES['file'])
            return HttpResponseRedirect('/success/url/')
    else:
        form = UploadFileForm()
    return render(request, 'upload.html', {'form': form})

In your case, you can use:

form = UserCreationForm(request.POST, , request.FILES)
    if form.is_valid():
        form.save()
        return redirect('account:login')

Notice that we have to pass request.FILES into the form’s constructor; this is how file data gets bound into a form.

  • Related