5

I have a profile page where I would like to allow a user to upload a profile picture. I can edit all of the text but cannot upload an image. It works if i add the image via the Admin, but not via the user's profile page on the website. Note that when created via admin--it is uploading correctly to the directory (profile_image) that i've specified in media folder. I've created some error handling on template page, but the error generated is this: "The 'image' attribute has no file associated with it." Below is my code:

models.py

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    first_name = models.CharField(default='',max_length=100 )
    last_name = models.CharField(default='',max_length=100)
    email = models.CharField(max_length=100, default='')
    date_birth = models.DateField(default=datetime.datetime.now())
    bio = models.TextField(default='')
    image = models.ImageField(upload_to='profile_image', blank=True)


def create_profile(sender, **kwargs):
    if kwargs['created']:
        user_profile = UserProfile.objects.create(user=kwargs['instance'])

post_save.connect(create_profile, sender=User)

views.py

@login_required
def edit_profile(request):
    profile = get_object_or_404(models.UserProfile)
    if request.method == 'POST':
        form = forms.EditProfileForm(data=request.POST, instance=profile)

        if form.is_valid():
            form.save()
            return redirect('/accounts/profile')
    else:
        form = forms.EditProfileForm(instance=profile)
        args = {'form':form}
        return render(request, 'accounts/edit_profile.html', args)

forms.py

from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserChangeForm

from . import models


class UserProfileForm(forms.ModelForm):
    class Meta:
        model = models.UserProfile
        fields = [
            'first_name',
            'last_name',
            'email',
            'date_birth',
            'bio',
            'image',
        ]


class EditProfileForm(UserProfileForm):
    model = models.UserProfile
    fields = [
        'first_name',
        'last_name',
        'email',
        'date_birth',
        'bio',
        'image',
    ]

settings.py

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'accounts/media')

edit_profile.html

{% extends "layout.html" %}

{% block title %}User Profile | {{ user }}{{ super }}{% endblock %}

{% block body %}
<h1>My Profile</h1>

<form action="" method="POST" enctype="multipart/form-data">{% csrf_token %}
{{ form.as_p}}
    <button type="submit">Save</button>
</form>

{% endblock %}

2 Answers 2

10

The file comes in request.FILES, not request.POST. Do the following in the view:

form = forms.EditProfileForm(data=request.POST, files=request.FILES, instance=profile)

See the documentation on file uploads:

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Yup--that's it. Thank you kindly--a big help.
Never forget to add "enctype='multipart/form-data'" in the corresponding <form> on your template, otherwise you'll scratch your head till there's not a single line of hair on it if there are still some.
0

Please check your folder permissions also, DRF is not throwing any permission errors for me.

For Mac use : sudo chmod 777 * For Live Server don't use this just check what is relevant and secure for your Os.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.