0

I tried updating a user's profile picture using a function view (ajax) but I keep getting the error below:

raise MultiValueDictKeyError(key) django.utils.datastructures.MultiValueDictKeyError: 'emp_photo'

The same technique I am using is being used on CharField and TextField without issues.

Please see below for my codes.

views.py

@login_required(login_url='/login/')
@user_passes_test(user_type_combo)
def change_employee_photo(request, pk):
    data = dict()
    profile = get_object_or_404(Profile, pk=pk)
    if request.method == 'POST':
        form = EmployeePhotoForm(request.POST or None, request.FILES or None, instance=profile)
        if form.is_valid():
            newPic = profile(emp_photo=request.FILES['emp_photo'])
            newPic.save()
            data['is_valid'] = True
    else:
        form = EmployeePhotoForm(instance=profile)
        data['form_is_valid'] = False

    context = {
        'form': form,
    }
    data['html_form'] = render_to_string('employees/partial_employee_photo.html',
                                         context,
                                         request=request
                                         )
    return JsonResponse(data)

forms.py

class EmployeePhotoForm(forms.ModelForm):
    class Meta:
        model = Profile
        fields = ['emp_photo',]


{% load crispy_forms_tags %}
<form action="{% url 'change_employee_photo' form.instance.pk %}" class="js-change-employee-photo-form"
      enctype="multipart/form-data" id="ProfileUpdateForm" method="post" runat="server">
    {% csrf_token %}
    <div class="modal-header">
        <h5 class="modal-title">Change Employee Photo</h5>
        <button aria-label="Close" class="close" data-dismiss="modal" type="button">
            <span aria-hidden="true">&times;</span>
        </button>
    </div>
    <div class="modal-body">
        <div class="form-group col">
            <div id="emp_photo_holder">
                <img alt="{{profile.first_name}}_{{profile.last_name}}" height="200px" id="emp_img"
                     src="/media/default.jpg/" width="200px"/>
                <input id="emp_photo" name="emp_photo" type="file" value="{{profile.emp_photo}}"/>
            </div>
        </div>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
        <script>

                function readURL(input) {
                  if (input.files && input.files[0]) {
                    var reader = new FileReader();

                    reader.onload = function(e) {
                      $('#emp_img').attr('src', e.target.result);
                    }

                    reader.readAsDataURL(input.files[0]);
                  }
                }

                $("#emp_photo").change(function() {
                  readURL(this);
                });


        </script>
    </div>
    <div class="modal-footer">
        <button class="btn btn-default" data-dismiss="modal" type="button">Close</button>
        <button class="btn btn-warning confirmation"
                onclick="return confirm('Are you sure you want upload a new photo for this employee?')"
                type="submit">
            <i class="fa fa-upload"></i> Upload
        </button>
    </div>
</form>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>

I will most definitely appreciate any help to have this issue resolved.

phagyrhe
  • 167
  • 1
  • 14
  • I guess the problem lies over here `newPic = profile(emp_photo=request.FILES['emp_photo'])` as you are updating the profile image you can try `profile.emp_photo.save('filename', fdata, True)`. See [this](https://stackoverflow.com/a/60049358/8601641) might help you. – k33da_the_bug Mar 29 '20 at 12:47

2 Answers2

0

i Guess you have forgot to mention the below lines in your settings.py

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

0

You can think of using request.FILES.getlist('emp_photo') and additionally check if emp_photo key exists by printing it in your code if it holds some value.

DARK_C0D3R
  • 2,075
  • 16
  • 21
  • The error `newPic.save() AttributeError: 'list' object has no attribute 'save'` was shown when I tried this method – phagyrhe Mar 29 '20 at 18:10
  • this request fetch you list of files, you need to play around with it to achieve required purpose, btw what are you getting if you just print(request.FILES.getlist('emp_photo')) as based on that you have to send req to emp_photo parameter in your profile() as it accepts emp_photo as single file not in format of list. So it might be getting [0] of it depending upon what is print(request.FILES.getlist('emp_photo')) output. – DARK_C0D3R Mar 29 '20 at 18:55
  • I tried `print(request.FILES.getlist('emp_photo'))` in console and it returned `Can't find file (request.FILES.getlist('emp_photo'))`. I guess there is something I am doing wrong which I need to figure out – phagyrhe Mar 29 '20 at 19:32
  • there is issue with attaching the file, your request says there is no file attached – DARK_C0D3R Mar 30 '20 at 01:50