Today we are going to upload image using django model. We’re going to create a small project where we can implement Django’s file upload, save and view functions, with a database but where the images will be stored on a hard drive. We assuming that you already configured your project. If you want to know configure django project see our blog Setup Your First Django Project .
So, this is our project structure
mysite/ manage.py mysite/ __init__.py settings.py urls.py asgi.py wsgi.py firstapp/ __init__.py admin.py apps.py migrations/ __init__.py models.py tests.py views.py
Configure media folder
To store files/images need to create media
folder in our root directory. configure your media
folder add these line into your setting.py file.
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
Creating the Model
Let’s start off by defining a model of a Profile
, which directly matches to a database table. A form can then be created to represent a blank slate of this model, allowing the user to fill in the details. In the firstapp/models.py
file, we can define a model that extends the models.Model class, which then inherits the functionality to be saved in the database:
from django.db import models
def user_directory_path(instance, filename):
# file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
return 'user_{0}/{1}'.format(instance.name, filename)
# Create your models here.
class Profile(models.Model):
name = models.CharField(max_length=100)
email = models.CharField(max_length=100,null=True,default="")
profile_picture = models.ImageField(upload_to=user_directory_path, blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
Here, profile_picture field’s datatype is ImageField which store a file path and set path to uploading image is in upload_to
attribute.
Here upload_to
attribute contain a custom function user_directory_path
which is responsible to create custom folder by name into media folder and upload image.
Now register our model into firstapp/admin.py
:
from django.contrib import admin
# Register your models here.
from .models import Profile
admin.site.register(Profile)
Now run command to migrate your model:
python manage.py makemigrations
Here you may get an error : ImageField because Pillow is not installed
To solve this error we need to run this command:
python -m pip install Pillow
Now, again run these 2 commands to migrate :
python manage.py makemigrations
python manage.py migrate
Create superuser for database
Now, create super user to login you database:
python manage.py createsuperuser
Enter your username and password to create superuser.
Registering URL Paths
let’s configure the URL paths that will allow a user to use this application. To do this, let’s create a urls.py file inside our app. Then we can go on and “include” its content in the project-level urls.py file.
Our mysite/urls.py
will look something like this:
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include("firstapp.urls")),
]
Our firstapp/urls.py
will look something like this:
from django.urls import path
from firstapp import views
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('', views.index,name="index"),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
The static() function maps the MEDIA_URL
, to the actual path to where our files reside, MEDIA_ROOT
. Requests that try to reach any of our files can get access via this MEDIA_URL
, which is automatically prefixed to the [url] attribute of ImageField instances.
Creating a Template to Display Our Form
To preserve our templates, let’s create a templates
folder into our root directory. The call is non-negotiable because Django will look for HTML templates only under the folders named templates. Now our project structure is look like
mysite/ manage.py mysite/ __init__.py settings.py urls.py asgi.py wsgi.py firstapp/ __init__.py admin.py apps.py migrations/ __init__.py models.py tests.py views.py templates/
Set template folder configuration into TEMPLATES
section in setting.py file:
'DIRS': [os.path.join(BASE_DIR,'templates')],
Inside our new folder, let’s add an index.html
file.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Upload Image</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
{% for message in messages %}
<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert">
<strong>{{ message }}</strong>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
{% endfor %}
<form action="/" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-group">
<label for="name">Name:</label>
<input type="text" class="form-control" id="name" placeholder="Enter name" name="name">
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="email" class="form-control" id="email" placeholder="Enter email" name="email">
</div>
<div class="form-group">
<label for="file">Picture:</label>
<input type="file" class="form-control" id="file" name="file">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</body>
</html>
The {% csrf_token %}
is another must-have for any form with action = “POST”. It is a completely unique token Django kindly creates for every customer to make sure safety while accepting requests.
View to save data
To store data and image file:
from django.shortcuts import render
from firstapp.models import Profile
from django.contrib import messages
# Create your views here.
def index(request):
if request.method == 'POST':
name = request.POST['name']
email = request.POST['email']
picture = request.FILES['file']
if Profile(name = name,email=email,profile_picture = picture).save():
messages.success(request, "Saved successfully")
return render(request,"index.html")
return render(request,"index.html")
When it is saved successfully you can see in media folder and you will find your image file in user_name folder :
That is it for today, hope it helps. If you have a better approach to resolve this problem please make a comment in comment section below.
—
If you like this article, you can buy me a coffee. Thanks!