#Profile Picture not displaying correctly when user uploads a photo

48 messages · Page 1 of 1 (latest)

scarlet echo
#

Hi, I am creating an app where users have a profile page that is supposed to display the number of pets they have registered, a profile picture and a bio. However, when I upload a picture, there is no associated photo on the user profile. Some code snippets can be found below:

Here is the code for the UserProfile model:

    user = models.OneToOneField(User, on_delete=models.CASCADE)
    image = models.ImageField(upload_to='profile_images', blank=True)
    bio = models.TextField(blank=True)

    def __str__(self):
        return f"{self.user.username}'s Profile"

Here is the associated view containing the logic for the profile view:

def profile_view(request):
    profile = request.user.userprofile
    pets = Pet.objects.filter(user=request.user).count()

    if request.method == 'POST':
        form = UserProfileForm(request.POST, request.FILES, instance=profile)
        if form.is_valid():
            form.save()
            return redirect('profile')
    else:
        form = UserProfileForm(instance=profile)
    
    return render(request, 'core/profile.html', {'form': form, 'pets': pets})

And finally, here is the template logic that I have set up:

        <img src="{{ profile.image.url }}" alt="Profile Picture" class="w-32 h-32 rounded-full mb-4">
    {% else %}
        <div class="w-32 h-32 rounded-full bg-gray-300 mb-4"></div>
    {% endif %}

TYIA

junior ether
#

When you say "there is no associated photo on the user profile" - do you mean the form upload errors, or it succeeds but no photo is shown?
What is your template code that's meant to be showing the photo?
How are you running Django - locally with runserver, or some other way?

scarlet echo
#

The form upload succeeds but no photo is shown is what I meant. Also, the template logic is just supposed to show and style the photo (if the user uploaded one) or show grey background otherwise. I am running Django locally with runserver

junior ether
#

IIRC, Django's runserver doesn't serve media files by default

scarlet echo
#

I'll try this and get back to you. Thanks for your help!

scarlet echo
#

Hello, I tried that solution and my image still does not appear on the page. I've tried debugging by looking at the profile.image.url and that returns empty, which is where I'm not sure what's happening. I checked the view and the image is being passed correctly and if I navigate to the image in my browser, it appears just fine

plush sage
#

if you navigate to the image url and it shows, this sounds to me like a media url issue in your settings.py

empty vortex
#

and upload form encoding type set, otherwise it won't upload files

cloud granite
#

Can you actually see the uploaded photo when you open the record in the admin?

scarlet echo
scarlet echo
#

I also wanted to note that the images serve just fine on a different template, which makes me think that there is an issue with the template itself. For example, I have an app called pets which contains a template called pet_detail which shows the user a detailed view of the pet they have registered. The pet photo appears just fine when I navigate to that page. However, the issue im having is within the petnote_core app and the profile template not serving the image correctly.

cloud granite
#

Is the image link actually in the rendered HTML?

#

If it is, what does the browser developer network view report about the request for the image?

scarlet echo
#

When I check the network tab, I don't see a request for that image, so I don't believe its being rendered in the html. When I put a <p> tag to debug and display the profile.image, it is empty as well

cloud granite
#

There is no profile context variable in the render call in the view code you shared?

#

You set a variable named profile, but is is not used in the context dict in the render call.

#

django-fastdev is a way to get errors on stuff like this

scarlet echo
#

I'm a bit confused, would you be able to hop on a VC call for 10 mins and explain it to me?

cloud granite
#

You shared the code for a view named profile_view above. On the last line you set two context variables, form and pets. In your template you are using another context variable named profile that you are not supplying to the template code you shared.

scarlet echo
#

Oh, one moment. I can share the code

cloud granite
#

You may be defining profile somewhere in the rest of the template, but i have a feeling you do not. Django does not by default throw any errors on missing context variables.

scarlet echo
#

Here is the associated code:

In profile.html, here is my logic for displaying the profile image (if a user uploads one) or showing a default gray placeholder:

        <img src="{{ profile.image.url }}" alt="Profile Picture" class="w-32 h-32 rounded-full mb-4">
    {% else %}
        <div class="w-32 h-32 rounded-full bg-gray-300 mb-4"></div>
    {% endif %}

In my views.py, I have a view that aims to display and save the form that a user submits to update their profile:

def profile_view(request):
    profile = request.user.profile
    pets = Pet.objects.filter(user=request.user).count()

    # If the request method is post, meaning they are updating their profile
    if request.method == 'POST':
        form = UserProfileForm(request.POST, request.FILES, instance=profile)
        if form.is_valid():
            print("Form is valid, saving profile...")
            form.save()
            return redirect('profile')
    else:
        form = UserProfileForm(instance=profile)
        print(form.errors)

    return render(request, 'core/profile.html', {'form': form, 'pets': pets})
cloud granite
#

Yes? I have already seen this code, you shared it before. My diagnosis and bug description still applies.

cloud granite
#

... the code for a view named profile_view ... On the last line you set two context variables, form and pets. In your template you are using another context variable named profile that you are not supplying to the template code you shared.

#

profile is neither form nor pets

scarlet echo
#

Oh I understand

#

Let me try changing this and get back to you

cloud granite
#

Also, maybe try django-fastdev as a way to make Django tell you about errors like this.

scarlet echo
#

Just installed it, thank you so much for your help thus far

cloud granite
#

I assume you also managed to fix the profile image?

scarlet echo
#

Not yet, Im working on it now

#

I tried adding the context variable profile to the last line in order to pass it to the template that I made, but still have the same issue

cloud granite
#

Show the code you changed?

scarlet echo
#
def profile_view(request):
    profile = request.user.userprofile
    pets = Pet.objects.filter(user=request.user).count()

    # If the request method is post, meaning they are updating their profile
    if request.method == 'POST':
        form = UserProfileForm(request.POST, request.FILES, instance=profile)
        if form.is_valid():
            print("Form is valid, saving profile...")
            form.save()
            return redirect('profile')
    else:
        form = UserProfileForm(instance=profile)

    return render(request, 'core/profile.html', {'form': form, 'pets': pets, 'profile': profile})
#

I feel like im not doing something correctly

junior ether
#

Do you get no image at all, or the placeholder grey image?

scarlet echo
#

The placeholder grey image

junior ether
#

Okay. Can you run the following for me?

python manage.py shell

from <app>.models import UserProfile
profile = UserProfile.objects.get(user__username="NAME_OF_LOGGED_IN_USER")
print(profile.image)
#

And copy/paste that entire thing to show us?

#

Replacing <app> and the username of the user as appropriate etc

scarlet echo
#

I was able to fix the issue. I was not correctly passing the profile object to the context portion of the view logic

junior ether
#

So your view is different to the one you pasted above?

scarlet echo
#

Only slightly, for some reason when I wrote the context like so, it works:

@login_required
def profile_view(request):
    profile = request.user.userprofile
    pets_count = Pet.objects.filter(user=request.user).count()

    if request.method == 'POST':
        form = UserProfileForm(request.POST, request.FILES, instance=profile)
        if form.is_valid():
            form.save()
            return redirect('profile')
    else:
        form = UserProfileForm(instance=profile)

    context = {
        'form': form,
        'pets': pets_count,
        'profile': profile,
    }
    return render(request, 'core/profile.html', context) ```
cloud granite
#

It should work either way. I am guessing either browser cache, or you forgot to save the file 😂