70
votes

When a user registers for my app.I receive this error when he reaches the profile page.

The 'image' attribute has no file associated with it.
Exception Type: ValueError 
Error during template rendering
In template C:\o\mysite\pet\templates\profile.html, error at line 6
1 <h4>My Profile</h4>
2  
3 {% if person  %}
4 <ul>           
5   <li>Name: {{ person.name }}</li>
6   <br><img src="{{ person.image.url }}">
Traceback Switch back to interactive view
File "C:\o\mysite\pet\views.py" in Profile
 71.     return render(request,'profile.html',{'board':board ,'person':person})

I think this error happens because my template requires a image and seen he just registered he can't add a image unless he go to the edit page and adds a page then he can access the profile page.

My profile.html

<h4>My Profile</h4>

{% if person  %}
<ul>           
    <li>Name: {{ person.name }}</li>
    <br><img src="{{ person.image.url }}">


</ul>
{% endif %}

My Profile function at views.py

def Profile(request):
    if not request.user.is_authenticated():
        return HttpResponseRedirect(reverse('world:LoginRequest'))
    board = Board.objects.filter(user=request.user)
    person = Person.objects.get(user=request.user)
    return render(request,'profile.html',{'board':board ,'person':person})

I tried this solution by creating a 2 instance of Person object and separating them at my template with a if but it didn't succeed.

<h4>My Profile</h4>

{% if person  %}
<ul>           
    <li>Name: {{ person.name }}</li>
 </ul>
{% endif %}
{% if bob %}
<ul>           
<br><img src="{{ bob.image.url }}">
</ul>

My solutions to the Profile function

def Profile(request):
    if not request.user.is_authenticated():
        return HttpResponseRedirect(reverse('world:LoginRequest'))
    board = Board.objects.filter(user=request.user)
    person = Person.objects.get(user=request.user)
    bob = Person.objects.get(user=request.user)

    return render(request,'profile.html',{'board':board ,'person':person,'bob':bob})

I'm been reading the documentation for Built-in template tags and filters I think a solution here is to use ( and ) template tag but I can't seem to use it properly.

How can I configure this template to make picture an option. If their are no picture leave it but display the persons name.

Thank you for helping me

8

8 Answers

99
votes

bob and person are the same object,

person = Person.objects.get(user=request.user)
bob = Person.objects.get(user=request.user)

So you can use just person for it.

In your template, check image exist or not first,

{% if person.image %}
    <img src="{{ person.image.url }}">
{% endif %}
85
votes

The better approach which would not violate DRY is to add a helper method to the model class like:

@property
def image_url(self):
    if self.image and hasattr(self.image, 'url'):
        return self.image.url

and use default_if_none template filter to provide default url:

<img src="{{ object.image_url|default_if_none:'#' }}" />
10
votes

My dear friend, others solvings are good but not enough because If user hasn't profile picture you should show default image easily (not need migration). So you can follow below steps:

Add this method to your person model:

@property
def get_photo_url(self):
    if self.photo and hasattr(self.photo, 'url'):
        return self.photo.url
    else:
        return "/static/images/user.jpg"

You can use any path (/media, /static etc.) but don't forget putting default user photo as user.jpg to your path.

And change your code in template like below:

<img src="{{ profile.get_photo_url }}" class="img-responsive thumbnail " alt="img">
4
votes

Not exactly what OP was looking for, but another possible solution would be to set a default value for ImageField:

 class Profile(models.Model):
    # rest of the fields here
    image = models.ImageField(
        upload_to='profile_pics/',
        default='profile_pics/default.jpg')
2
votes

i think your problem in model field, try to put a default image value , like this :

PRF_image = models.ImageField(upload_to='profile_img', blank=True, null=True , default='profile_img/925667.jpg')
1
votes

You can also use the Python 3 built-in function getattr to create your new property:

@property
def image_url(self):
    """
    Return self.photo.url if self.photo is not None, 
    'url' exist and has a value, else, return None.
    """
    if self.image:
        return getattr(self.photo, 'url', None)
    return None

and use this property in your template:

<img src="{{ my_obj.image_url|default_if_none:'#' }}" />
1
votes

Maybe this helps but my database didn't save on of the pictures for the object displayed on the page.

As that object in models.py has blank=False and also I am looping through object, it constantly gave an error until I added a replacement picture in the admin for the database to render.

0
votes

This error also arises when any one or more items doesn't have an image added and the rest items do. To fix this:

class Product(models.Model):
    pname = models.CharField(max_length=30)
    price = models.IntegerField()
    img = models.ImageField(null = True,blank = True)
    def __str__(self):
        return self.pname
    @property
    def imageURL(self):
        try:
            url = self.img.url
        except:
            url=''
        return url