# Simple Django Tip #9

Image attribute: [Social media illustrations by Storyset](https://storyset.com/social-media)

### Introduction

I started to write about Django tips in concurrence to my development with a [product I'm building](https://usewobu.com). As and when I complete developing a logical step, I take the crux of it and share it in a post. As I wanted to share my progress in public, I thought this would be an aspect to it 💁‍♀️.

In my [previous post on Django tips](https://hellosambhavi.com/simple-django-tip-8), we looked at how to conditionally navigate post successful login. In this post, let's look at different ways to provide a default image to your profile picture aka avatar. I chose this one as it's common practice for every single User model to have a placeholder for a profile picture.

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">I've noticed that I grasp a concept easily when explained with a business case or a real life example rather than a foo bar type of an explanation. Hence I try to apply the same whenever I explain a concept. Hence the need for '<strong>avatar</strong>' 🕵️‍♀️ in this post. But it holds good for any scenario where there is a need for a default image 🎨</div>
</div>

### Different Approaches

For the sake of the post, let's define a `CustomUser` model like so 👇

```python
class CustomUser(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(unique=True)
    display_name = models.CharField(max_length=20, \
                            null=True, blank=True)
    first_name = models.CharField(max_length=150, \
                            validators=[validators.validate_aplhabets_only],\
                                null=True, blank=True)
    last_name = models.CharField(max_length=150, 
                            validators=[validators.validate_aplhabets_only], \
                                 null=True, blank=True)
    avatar = models.ImageField(<< will be expplained below >>)
    contact_number = models.CharField(max_length=25, null=True, blank=True)
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)
    is_active = models.BooleanField(default=False)
    # denotes whether the user clicked on activation/confirmation link
    is_account_verified = models.BooleanField(default=False)
    # denotes the date when the user joined the platform
    date_added = models.DateTimeField(auto_now_add=True)

    USERNAME_FIELD = "email"
    REQUIRED_FIELDS = []

    objects = CustomUserManager()

    
    def __str__(self):
        return f"{self.email}"
```

The column `avatar` is the one that is of interest. There are multiple ways to handle it and let's look at a couple of them.

1. **Default Image while defining the Model**
    
    We can provide a default path to the user's avatar. Just make sure to load the image in the mentioned folder. Usually it will resemble one of the images shown [in this link](https://pngtree.com/so/default-avatar).
    
    ```python
    avatar = models.ImageField(upload_to="avatars/", null=True, blank=True, default='path/to/default/avatar.jpg')
    ```
    
    This is one of the most straight forward method to handle a default image.
    
2. **Default Image while accessing the image in the Template**
    
    If we do not want a default image in the Model as modifying something in the model will lead to migrations and it's better not to keep changing details in a Django Model. An alternate approach will be to handle it directly in the template itself.
    
    If the user's avatar column has a value, then that is used, else the default image.
    
    <div data-node-type="callout">
    <div data-node-type="callout-emoji">💡</div>
    <div data-node-type="callout-text">One needs to upload the default image in this case too</div>
    </div>
    
    ```python
    {% if user.avatar %}
        <img src="{{ user.avatar.url }}" alt="User avatar">
    {% else %}
        <img src="{% static 'path/to/default/avatar.jpg' %}" alt="Default avatar">
    {% endif %}
    ```
    
    Note the usage of `{% static %}` template tag in case of default image.
    
    💡 Do not forget to `{% load static %}`
    
3. **Using a Helper function in the Model definition class**
    
    A third approach is to use a helper function in the Model class of `CustomUser`. This function will return the avatar url if it has been set else the path to the default. ⭐In my opinion, this is a much cleaner approach as all things `CustomUser` is within the Model itself without altering any aspect at a column definition.
    
    ```python
    class CustomUser(AbstractBaseUser, PermissionsMixin):
        # ...
    
        def get_avatar_url(self):
            if self.avatar and hasattr(self.avatar, 'url'):
                return self.avatar.url
            else:
                return 'path/to/default/avatar.jpg'
    ```
    
    We then access the function directly in the template like so 👇
    
    ```python
    <img src="{{ user.get_avatar_url }}" alt="User avatar">
    ```
    
4. **Using a templatetag**
    
    In case your project has a lot of image fields with a need for default, then consider using templatetags.
    
    <div data-node-type="callout">
    <div data-node-type="callout-emoji">💡</div>
    <div data-node-type="callout-text">If you are interested to learn more about templatetags, here is a <a target="_blank" rel="noopener noreferrer nofollow" href="https://docs.djangoproject.com/en/5.0/howto/custom-template-tags/" style="pointer-events: none">good one from Django documentation.</a> I plan to write a separate post about <code>templatetags</code> in near future 😁</div>
    </div>
    

Create a folder in your django project and name it `templatetags`. Create all your custom tags under this folder. For our avatar, let's create a file and name it `image_tags.py`.

As a first step, create an instance for `template.Library()`. Write a simple function that returns the default image if the user's avatar is not set, else return the set avatar url.

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Don't forget to add the decorator!</div>
</div>

```python
from django import template

register = template.Library()

@register.simple_tag
def get_avatar_url(user):
    return user.avatar.url if user.avatar else 'path/to/default/avatar.jpg'
```

In your template, you can make use of the newly created custom tag like so 👇

```python
{% load image_tags %}

<img src="{% get_avatar_url user %}" alt="User avatar">
```

### Conclusion

This is a short post that talks about four different approaches when you need to show an image by default for an `ImageField` in Django. Factors to keep in mind while choosing in approach can be:

* Is it an one off case?
    
* Are there a lot of image fields?
    
* Not many developers are going to touch the code base
    
* Size of the Django project
    
    Hope you liked this post and don't forget to share the approach that you usually take 😁
