Simple Django Tip #9
How to provide a default image for your Profile picture?
Table of contents
Image attribute: Social media illustrations by Storyset
Introduction
I started to write about Django tips in concurrence to my development with a product I'm building. 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, 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.
Different Approaches
For the sake of the post, let's define a CustomUser
model like so π
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.
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.
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.
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.
π‘One needs to upload the default image in this case too{% 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 %}
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 thingsCustomUser
is within the Model itself without altering any aspect at a column definition.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 π
<img src="{{ user.get_avatar_url }}" alt="User avatar">
Using a templatetag
In case your project has a lot of image fields with a need for default, then consider using templatetags.
π‘If you are interested to learn more about templatetags, here is a good one from Django documentation. I plan to write a separate post abouttemplatetags
in near future π
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.
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 π
{% 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 π