Lập trình hệ thống đặt vé xem phim bằng Django không khó. Dưới đây là hướng dẫn chi tiết từng bước cách đặt vé xem phim bằng Django.
Đầu tiên, chúng ta sẽ tạo trang chủ liệt kê tất cả phim hiện có có sẵn cho việc đặt vé. Khi khách hàng muốn đặt vé, họ phải tạo tài khoản, rồi click vào nút Book. Vé đã đặt sau đó sẽ hiện trong phần chờ xử lý. Tại đây, bạn có lựa chọn hủy vé, thanh toán và xem tổng số vé đã đặt.
Hệ thống đặt vé bằng Django
Sau đây là các bước tạo web đặt vé bằng Django:
Khởi động thư mục dự án
Để khởi động dự án, dùng lệnh này:
django-admin startproject core
cd core
Để khởi động app dùng lệnh này:
python manage.py startapp home
Giờ thêm app này vào ‘settings.py’
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"home",
]
Cấu trúc file:
Thiết lập file
Models.py: File này được dùng để tạo các mẫu: BaseModel,MovieCategory,CartItems. Mẫu được dùng cho việc lưu trữ thông tin trong database.
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: Code này xác định các trình xem xử lý những trang web khác nhau trong ứng dụng web Django. Các cửa sổ xem bao gồm trang chủ, trang đăng nhập, trang đăng ký, giỏ mua hàng và loại bỏ các mục từ giỏ hàng.
- Xác thực người dùng: Nó sử dụng hệ thống xác thực có sẵn của Django cho đăng ký và đăng nhập người dùng. Người dùng có thể tạo tài khoản bằng tên người dùng và mật khẩu. Code này kiểm tra tên người dùng có sẵn và xử lý xác thực.
- Hiện phim: Trình xem ‘home” truy xuất một danh sách các bộ phim từ database và chuyển chúng tới mẫu ‘home.html’ để hiển thị. Điều này cho phép người dùng xem một danh sách các bộ phim trên trang chủ.
- Quản lý giỏ hàng: Người dùng có thể thêm phím vào giỏ hàng. Trang ‘add_cart’ sẽ xử lý vấn đề này bằng cách liên kết phim với giỏ hàng của người dùng nằm trong database. Trang ‘cart’ hiện nội dung trong giỏ hàng của người dùng.
- Xử lý và thông báo lỗi: Code này xử lý lỗi và các ngoại lệ. Nó hiện thông báo lỗi phù hợp bằng framework ‘messages’ của Django để báo cho người dùng biết các lỗi như thông tin đăng nhập không chính xác hoặc các vấn đề về đăng ký.
- Decorator xác thực: ‘@login_required‘ được dùng để bảo vệ các trình xem cụ thể. Nó đảm bảo chỉ người dùng đã được xác thực mới có quyền truy cập giỏ hàng hoặc loại bỏ chúng khỏi nó. Nếu người dùng không được xác thực, ứng dụng sẽ đưa họ về trang đăng nhập.
{% 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>
Tạo GUI
Base.html: Đây là file HTML cơ bản của web mà hiện logo của trang. File này được kế thừa bởi tất cả file HTML khác.
{% 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: Đây là file HTML được dùng để xem trang chủ của web. Bạn có thể nhìn thấy mọi sản phẩm của web tại đây và thêm chúng vào giỏ hàng nếu muốn.
{% 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 %}
Register.html: Trang HTML này được dùng để thu thập thông tin người dùng và sử dụng nó để đăng ký người dùng.
{% 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: Nó hiện thông tin liên quan như số seri, lựa chọn hủy vé, ảnh, tên phim và link để thanh toán. Nội dung năng động này được tạo dựa trên các mục có trong giỏ hàng của người dùng.
{% 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: Code này chịu trách nhiệm định tuyến và phục vụ các trang web trong ứng dụng Django khi xử lý các tệp phương tiện và file tĩnh dựa trên cài đặt của ứng dụng.
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()
Triển khai dự án
Chạy lệnh này để áp dụng di chuyển:
python3 manage.py makemigrations
python3 manage.py migrate
Chạy server này với sự trợ giúp của lệnh sau:
python3 manage.py runserver
Kết quả:
Hi vọng bài viết hữu ích với các bạn!