Open In App

Movie Ticket Booking using Django

Last Updated : 26 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

In this article, we will create a Movie Ticket Booking system using Django. To begin, we will create the first homepage where we can view all the movies that are currently available for booking. In order to book a ticket, the first step is to create an account on the platform. Once you have created an account, you can book a ticket by clicking the “Book” button. The booked ticket will then be displayed in your pending bookings section. From the pending bookings section, you have the option to cancel the ticket, make a payment for the ticket, and view the total number of tickets you have booked up to that point.

Movie Ticket Booking using Django

Here we will see the steps for creating a Movie Ticket Booking Website using Django.

To install Django follow these steps.

Starting the Project Folder

To start the project use this command

django-admin startproject core
cd core

To start the app use this command

python manage.py startapp home

Now add this app to the ‘settings.py’

 INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"home",
]

File Structure

file-movie

Setting up the files

models.py: This file is used to create the models BaseModel,MovieCategory,CartItems. Models are used for storing the information in the database.

Python3
from django.db import models
from django.contrib.auth.models import User
import uuid
 
class BaseModel(models.Model):
    uid = models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True)
    created_at = models.DateField(auto_now_add=True)
    updated_at = models.DateField(auto_now_add=True)
     
    class Meta:
        abstract = True
         
class MovieCategory(BaseModel):
    category_name = models.CharField(max_length=100)
     
class Movie(BaseModel):
    category = models.ForeignKey(MovieCategory, on_delete=models.CASCADE, related_name="pizzas")
    movie_name = models.CharField(max_length=100)
    price = models.IntegerField(default=100)
    images = models.CharField(max_length=500)
     
class Cart(BaseModel):
    user = models.ForeignKey(User, null=True, blank=True, on_delete=models.SET_NULL, related_name="carts")
    is_paid = models.BooleanField(default=False)
     
class CartItems(BaseModel):
    cart = models.ForeignKey(Cart, on_delete=models.CASCADE, related_name="cart_items")
    movie = models.ForeignKey(Movie, on_delete=models.CASCADE)

views.py: The code defines views that handle different web pages in a Django web application. There are views for the home page, login page, registration page, shopping cart, and removing items from the cart.

  1. User Authentication: It uses Django’s built-in authentication system for user registration and login. Users can create an account with a username and password, and the code checks for username availability and handles authentication.
  2. Displaying Movies: The ‘home’ view retrieves a list of movies from the database and passes them to the ‘home.html’ template for rendering. This allows users to view a list of movies on the home page.
  3. Shopping Cart Management: Users can add movies to their shopping cart. The ‘add_cart‘ view handles this by associating a movie with the user’s cart, which is stored in the database. The ‘cart’ view displays the user’s cart contents.
  4. Error Handling and Messages: The code handles errors and exceptions. It displays appropriate error messages using Django’s ‘messages’ framework to inform users about issues such as incorrect login credentials or registration problems.
  5. Authentication Decorators: The ‘@login_required‘ decorator is used to protect certain views. It ensures that only authenticated users can access their shopping cart or remove items from it. If a user is not authenticated, they are redirected to the login page.
Python3
from django.shortcuts import render, redirect
from .models import *
from django.contrib import messages
from django.contrib.auth import login, authenticate
from django.contrib.auth.decorators import login_required
def home(request):
    movies = Movie.objects.all()
    context = {'movies': movies}
    return render(request, "home.html", context)
def login_page(request):
    if request.method == "POST":
        try:
            username = request.POST.get('username')
            password = request.POST.get('password')
            user_obj = User.objects.filter(username=username)
             
            if not user_obj.exists():
                messages.error(request, "Username not found")
                return redirect('/login/')
             
            user_obj = authenticate(username=username, password=password)
             
            if user_obj:
                login(request, user_obj)
                return redirect('/')
             
            messages.error(request, "Wrong Password")
            return redirect('/login/')
         
        except Exception as e:
            messages.error(request, "Something went wrong")
            return redirect('/register/')
     
    return render(request, "login.html")
def register_page(request):
    if request.method == "POST":
        try:
            username = request.POST.get('username')
            password = request.POST.get('password')
            user_obj = User.objects.filter(username=username)
             
            if user_obj.exists():
                messages.error(request, "Username is taken")
                return redirect('/register/')
             
            user_obj = User.objects.create(username=username)
            user_obj.set_password(password)
            user_obj.save()
             
            messages.success(request, "Account created")
            return redirect('/login/')
         
        except Exception as e:
            messages.error(request, "Something went wrong")
            return redirect('/register/')
     
    return render(request, "register.html")
@login_required(login_url="/login/")
def add_cart(request, movie_uid):
    user = request.user
    movie_obj = Movie.objects.get(uid=movie_uid)
     
    cart, _ = Cart.objects.get_or_create(user=user, is_paid=False)
    cart_items = CartItems.objects.create(cart=cart, movie=movie_obj)
     
    return redirect('/')
@login_required(login_url='/login/')
def cart(request):
    cart = Cart.objects.get(is_paid=False, user=request.user)
    context = {'carts': cart}
    return render(request, "cart.html", context)
@login_required(login_url='/login/')
def remove_cart_item(request, cart_item_uid):
    try:
        CartItems.objects.get(uid=cart_item_uid).delete()
        return redirect('/cart/')
    except Exception as e:
        print(e)

Creating GUI

base.html: This is the base HTML file of the website which displays the “GeeksForGeeks” logo.This file is inherited by all the other HTML files .

HTML
{% load static %}
<!doctype html>
<html lang="en">
 
<head>
  <!-- Required meta tags -->
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
 
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
    integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
 
 
  <title>Hello, world!</title>
  <style>
    h1 {
      color: green;
      font-size: 45px;
    }
    #log{
      color:black;
    }
  </style>
</head>
 
<body>
 
  <nav class="navbar navbar-dark bg-light shadow-lg">
    <div class="container-fluid">
      <a href="{% url 'home' %}" class="navbar-brand"> <strong style="font-size: 30px; color:black;"> 
        ???? Movie Ticket Booking </strong></a>
      <div class="d-flex">
        {% if request.user.is_authenticated %}
        <a href="https://www.geeksforgeeks.org/" class="btn btn-success"><i id="g" class="fas fa-globe"></i> Visit Website</a>
        <a class="btn btn-danger" href="{% url 'cart' %}"><i class="fas fa-hourglass-half"></i>  Pending <strong>
            {{ request.user.get_cart_count }}</strong></a>
 
        {% else %}
        <a href="{% url 'login' %}" class="navbar-brand " id="log">Login</a>
        <a href="{% url 'register' %}" class="navbar-brand " id="log">Register</a>
        {% endif %}
      </div>
    </div>
  </nav>
  <br>
  <h1 class="text-center "> GeeksforGeeks 
    </h1>
 
  {% block start %}{% endblock %}
 
  <!-- Optional JavaScript; choose one of the two! -->
 
  <!-- Option 1: Bootstrap Bundle with Popper -->
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
    integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
    crossorigin="anonymous"></script>
 
  <!-- Option 2: Separate Popper and Bootstrap JS -->
  <!--
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js" integrity="sha384-IQsoLXl5PILFhosVNubq5LC7Qb9DXgDA9i+tQ8Zj3iwWAwPtgFTxbJ8NT4GN1R8p" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.min.js" integrity="sha384-cVKIPhGWiC2Al4u+LWgxfKTRIcfu0JTxR+EQDz/bgldoEyl4H0zUF0QKbrJ0EcQF" crossorigin="anonymous"></script>
    -->
</body>
 
</html>

home.html: This HTML file is used to view the homepage of the website.Here all the products of the website can be seen and can be added to the cart.

HTML
{% extends "base.html" %}
 
{% load static %}
 
{% block start %}
 
<style>
    .bold{
        margin-left: 57px;
    }
    .middle{
        margin-left: 26%;
    }
</style>
<div class="container mt-5 pt-3">
    <div class="row">
    {% for movie in movies %}
    <div class="col-md-3 pt-3">
        <div class="card shadow-lg" style="width: 18rem;">
            <img src="{{movie.images}}" style="height: 210px; border-radius: 30px;" alt="Veg Pizza Image">
            <div class="card-body">
                <h5 class="card-title text-center text-uppercase">  <strong style="font-size: 28px; color:red">{{movie.movie_name}}</strong></h5>
                <p class="bold"> <b>Ticket Price -</b> ₹ {{movie.price}} <br> <strong>Session</strong> - {{movie.category.category_name}}</p>
                 <a href="{%  url 'add-cart' movie.uid %}" class="btn btn-warning middle" > 
                    ????️  Book </a>
                   </div>
        </div>
        <br>
    </div>
    <br>
    {% endfor %}
</div>
</div>
{% endblock %}

login.html: This HTML file is used for collecting the user credentials and then logging in the user.

HTML
{% extends "base.html" %}
 
{% load static %}
 
{% block start %}
<style>
  #goal {
    border-radius: 35px;
  }
 
  .mid {
    margin-left: 42%;
  }
</style>
 
<div class="container mt-5 mx-auto col-md-3 card shadow p-5" id="goal">
  <div class="login-form">
    {% if messages %}
    {% for message in messages %}
    <div class="alert alert-danger {{ message.tags }}" role="alert">
      {{ message }}
    </div>
    {% endfor %}
    {% endif %}
    <form action="" method="post">
      {% csrf_token %}
      <h2 class="text-center">Login </h2>
      <div class="form-group">
 
        <input type="text" class="form-control" name="username" placeholder="Username" required>
 
      </div>
      <div class="form-group mt-4">
        <input type="password" class="form-control" name="password" placeholder="Password" required>
      </div>
      <div class="form-group mt-4">
        <button class="btn btn-warning btn-block mid">Log In </button>
      </div>
 
 
    </form>
    <p class="text-center"><a href="{% url 'register' %}">Create an Account</a></p>
  </div>
 
</div>
{% endblock %}

register.html: This HTML page is used for collecting the user information and use it for registering the user.

HTML
{% extends "base.html" %}
 
{% load static %}
 
{% block start %}
<style>
    #goal {
        border-radius: 35px;
    }
 
    .mid {
        margin-left: 42%;
    }
</style>
 
 
<div class="container mt-5 mx-auto col-md-3  card shadow p-5" id="goal">
    <div class="login-form">
        {% if messages %}
        {% for message in messages %}
        <div class="alert alert-danger {{ message.tags }}" role="alert">
            {{ message }}
        </div>
        {% endfor %}
        {% endif %}
 
        <form action="" method="post">
            {% csrf_token %}
            <h2 class="text-center">Register </h2>
            <div class="form-group">
                <input type="text" class="form-control" name="username" placeholder="Username" required>
 
            </div>
            <div class="form-group mt-4">
                <input type="password" class="form-control" name="password" placeholder="Password" required>
            </div>
            <div class="form-group mt-4">
                <button class="btn btn-warning btn-block mid">Register </button>
            </div>
 
 
        </form>
        <p class="text-center"><a href="{% url 'login' %}">Already have a Account</a></p>
    </div>
 
</div>
{% endblock %}

cart.html: It displays relevant information such as the serial number, an option to cancel the ticket, an image, movie name, and a link to pay. This dynamic content is generated based on the items in the user’s shopping cart.

HTML
{% extends "base.html" %}
 
{% load static %}
 
{% block start %}
 
<style>
 
</style>
<div class="container card shadow-lg mt-5 ">
    <table class="table">
        <thead>
            <tr>
                <th scope="col">S.No.</th>
 
                <th scope="col">Cancel Toicket</th>
 
                <th scope="col">Book </th>
                <th scope="col">Movie Name</th>
                <th scope="col">Watch</th>
 
            </tr>
        </thead>
        <tbody>
            {% for cartItems in carts.cart_items.all %}
            <tr>
                <th scope="row">{{forloop.counter}}</th>
                <td><a href="{% url 'remove_cart' cartItems.uid %}" class="btn btn-danger">????️ Cancel Ticket</a>
                </td>
                <td><img src="https://i.ibb.co/Dkz0p6G/gfg-movei-3.jpg" style="height: 100px; width:100px;"></td>
                <td>
                    <h5>{{cartItems.movie.movie_name}}</h5>
                </td>
                <td><a href="https://www.geeksforgeeks.org/" class="btn btn-warning">
                        ???? Pay Now</a>
 
 
            </tr>
            {% endfor %}
            <tr>
 
                <th scope="col"></th>
                <td></td>
                <td></td>
                <td></td>
 
            </tr>
 
        </tbody>
    </table>
</div>
 
 
 
 
{% endblock %}

urls.py: The code is responsible for routing and serving web pages in a Django web application while handling media and static files based on the application’s settings.

Python3
from django.contrib import admin
from django.urls import path
from home.views import *
from django.conf.urls.static import static
from django.conf import settings
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
 
urlpatterns = [
    path('', home, name='home'),
    path('cart/', cart, name='cart'),
    path('remove_cart_item/<cart_item_uid>', remove_cart_item, name='remove_cart'),
    path('add_cart/<movie_uid>', add_cart , name="add-cart"),
    path('login/', login_page, name="login"),
    path('register/', register_page, name="register"),
    path("admin/", admin.site.urls),
]
 
if settings.DEBUG :
    urlpatterns +=static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
     
urlpatterns += staticfiles_urlpatterns()

admin.py: Here we are registering the models in admin.py file.

Python3
from django.contrib import admin
from .models import *
admin.site.register(MovieCategory)
admin.site.register(Movie)
admin.site.register(Cart)
admin.site.register(CartItems)

Deployement of the Project

Run these commands to apply the migrations:

python3 manage.py makemigrations
python3 manage.py migrate

Run the server with the help of following command:

python3 manage.py runserver

Output







Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads