ImageField and ModelForm image preview
I have Profile class in my models.py:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.png', upload_to=path_and_rename)
def __str__(self):
return f'{self.user.username} Profile'
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
img = Image.open(self.image.path)
if img.height > 300 or img.width > 300:
output_size = (300, 300)
img.thumbnail(output_size)
img.save(self.image.path)
and ProfileUpdateForm, for editing profile, in my forms.py:
class ProfileUpdateForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['image']
I'm passing ProfileUpdateForm as context(p_form) to my html file and displaying it with crispy:
profile.html
{% extends 'blog/base.html' %}
{% load crispy_forms_tags %}
{% block body %}
<div class="post">
<div class="content-section">
<div class="media">
<img class="rounded-circle account-img" src="{{ user.profile.image.url }}">
<div class="media-body">
<h2 class="account-heading">{{ user.username }}</h2>
<p class="text-secondary">{{ user.email }}</p>
</div>
</div>
</div>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<fieldset>
<legend class="border-bottom mb-4">Update Profile</legend>
{{ u_form|crispy }}
{{ p_form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit"> Update </button>
<a class="btn btn-outline-danger" href="{% url 'user-delete' user.id %}">Delete Profile</a>
</div>
</form>
<div class="border-top pt-3">
<small class="text-muted">Already Have an Account?
<a href="{% url 'login' %}" class="ml-2">Sign In</a>
</small>
</div>
</div>
{% endblock body %}
All profile has is image, so I'm displaying u_form(UserUpdateForm, for username and email updating) and right after it p_form(ProfileUpdateForm)
when image is chosen, it displays only name of the file.
I want image to be displayed alongside/instead of its name when user has chosen it in form, is there a way to do it?
Django itself can't help you. You have to use Javascript to fulfill your wish.There are a lot of libraries that do this for you, but you can achieve what you want without using libraries and only with JS. Check the answer to this question
If you want to add an image preview functionality for an ImageField in a Django ModelForm, you can achieve this by using JavaScript to handle the preview on the client side. Here's an example:
Assuming you have a model with an ImageField and a corresponding form:
models.py
from django.db import models
class YourModel(models.Model):
image = models.ImageField(upload_to='images/')
# other fields
# forms.py
from django import forms
from .models import YourModel
class YourModelForm(forms.ModelForm):
class Meta:
model = YourModel
fields = ['image', 'other_field1', 'other_field2']
Add other fields as needed
Now, in your template (your_template.html), you can include the necessary JavaScript to handle image preview:
<form method="post" enctype="multipart/form-data" id="yourForm">
{% csrf_token %}
{{ form.as_p }}
<img id="imagePreview" src="#" alt="Image Preview" style="display: none; max-width: 300px; max-height: 300px;">
<input type="submit" value="Submit">
</form>
<script>
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#imagePreview').attr('src', e.target.result);
$('#imagePreview').show();
}
reader.readAsDataURL(input.files[0]);
}
}
$("#id_image").change(function () {
readURL(this);
});
</script>
In this example, the JavaScript function readURL is used to read the selected image file and display a preview. The change event is bound to the #id_image input field (generated by Django for the ImageField), triggering the preview update whenever a new image is selected.
Make sure to include this script at the end of your HTML body or wrap it in a document-ready function ($(document).ready(function() { /* your script here */ });) to ensure that the DOM elements are loaded before the script runs.

