Creating an event booking website with a QR system — Part 3 (Simplifying the task)
So I initially had software in mind, that would take payments and send the tickets to the attendees on spot. But I am on a time crunch here.
But trying to build this for an upcoming event in a very few days takes a lot of work. So I am making a simpler version, which I will update very soon to the exact one I need.

So the next part is the bulk ticket generator using python.
I am going to use a different method involving HTML and CSS in the second version of this software for making amazing-looking tickets but for now, have made a basic version.
You can find the code on my GitHub profile
Here is the workflow
- Create a Razorpay account
- Create a button for payment
- Test the button, download the payment report
- Using python to generate multiple tickets
- Sending the tickets through the mail
So I am not going to talk about Razorpay setup, because it’s very simple and if you face an issue you can call their customer care and fix it (also it takes time to set up). Razorpay also solves our problem of generating random order numbers.
Creating a button is also very simple, you can explore and find out how to create a button and test it and get a report in .csv format.
Here is what the table should look like:

Also, I have duplicated the entry for now, but in real time you will get multiple entries.
So every night I will need to download the report manually and run the code to send the mail (I know this sucks but this is going to be the first version)
Also, I am writing the code in the worst possible way i.e. not organizing the code into different segments and making it look ugly. I will fix all those things in my second version of this software which will be launched soon(hopefully).
So last time(Part 2) we had our code for generating pdfs, I will be adding the same code in a different segment this time.
import pandas as pd
from fpdf import FPDF
import pyqrcode
import png
import os
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
You can find these libraries here:
- https://docs.python.org/3/library/smtplib.html // For sending emails
- https://docs.python.org/3/library/email.mime.html // For creating emails (explore around for adding images)
- https://pandas.pydata.org/docs/getting_started/index.html // for reading data
I have covered the other libraries in a previous post so refer here.
df = pd.read_excel('payment_links_excel.xlsx')
tickets = df.to_dict(orient='records')
This segment is to read the data and add it to a dictionary so that we can later use them individually for printing tickets.
for ticket in tickets:
pdfGen = {'name': ticket['full_name'], 'event': ticket['payment button title'],
'venue': 'Where ever you find space', 'role': 'ATTENDEE',
'date_time_event': '28 February 2023, 4PM to 7PM', 'order_no': ticket['order_id'],
'payment_status': ticket['payment status'], 'email_id': ticket['email']}
PAYMENT_STATUS = ""
if pdfGen['payment_status'] == 'captured':
PAYMENT_STATUS = "PAID"
else:
PAYMENT_STATUS = "UNPAID"
EVENT_NAME = pdfGen['event']
DATE_TIME_EVENT = pdfGen['date_time_event']
VENUE_EVENT = pdfGen['venue']
PER_NAME = pdfGen['name']
ROLE = pdfGen['role']
ORDER_NO = pdfGen['order_no']
PAYMENT_STATUS = ""
EMAIL_ID = pdfGen['email_id']
Yeah this is the ugly, unorganized code I am going to fix
class PDF(FPDF):
def header(self):
# Logo
self.image('Event_Logo.png', 10, 8, 33)
# Arial bold 15
self.set_font('Arial', 'B', 15)
# Move to the right
self.cell(80)
# Title
self.cell(30, 10, 'Entry Pass')
# Line break
self.ln(20)
def heading(self, EVENT_NAME):
self.cell(80)
# Font
self.set_font("Arial", 'B', 40)
# Event name
self.cell(30, 30, EVENT_NAME, 0, 0, 'C')
def date_time_venue(self, DATE_TIME_EVENT, VENUE_EVENT):
self.cell(40)
# Font
self.set_font("Arial", 'B', 10)
# DATE_TIME_VENUE
self.cell(-110, 76, DATE_TIME_EVENT, 0, 0, 'C')
self.cell(110, 88, VENUE_EVENT, 0, 0, 'C')
def attendee_name(self, PER_NAME):
self.set_y(70)
self.set_font("Arial", 'B', 25)
# ATTENDEE NAME
self.cell(60, 50, PER_NAME, 0, 0, 'L')
# self.cell(65, 58, ROLE, 0, 0, 'C')
def role_in_event(self, ROLE):
self.set_y(76)
self.set_font("Arial", 'I', 10)
# Role in Event
self.cell(60, 52, f"ROLE: {ROLE}", 0, 0, 'L')
def payment_status(self, PAYMENT):
self.set_y(-37)
self.set_font("Arial", '', 10)
# Payment Status
self.cell(0, 10, PAYMENT_STATUS, 0, 0, 'L')
def order_number(self, order_no):
self.set_x(-75)
self.set_font("Arial", '', 10)
# Order Number
self.cell(0, 10, f"Order Number: {ORDER_NO}", 0, 0, 'L')
def qr_code(self):
# QR_CODE
url = pyqrcode.create(ORDER_NO)
url.png(f"{PER_NAME}_ticket.png", scale=6)
self.image(name=f"{PER_NAME}_ticket.png", x=155, y=85, w=25, h=25)
# Page footer
def footer(self):
# Position at 1.5 cm from bottom
self.set_y(-15)
# Arial italic 8
self.set_font('Arial', 'I', 8)
# Page number
self.cell(0, 10, 'Page ' + str(self.page_no()) + '/{nb}', 0, 0, 'C')
Read about this code in the previous post (part 2)
pdf = PDF(format='A5', orientation='L')
pdf.alias_nb_pages()
pdf.add_page()
pdf.set_font('Times', '', 12)
pdf.heading(EVENT_NAME=EVENT_NAME)
pdf.date_time_venue(DATE_TIME_EVENT=DATE_TIME_EVENT, VENUE_EVENT=VENUE_EVENT)
pdf.attendee_name(PER_NAME=PER_NAME)
pdf.role_in_event(ROLE=ROLE)
pdf.payment_status(PAYMENT=PAYMENT_STATUS)
pdf.order_number(order_no=ORDER_NO)
pdf.qr_code()
pdf.output(f"{PER_NAME}_ticket.pdf", 'F')
This creates our PDF
# Login credentials
gmail_user = 'ENTER_YOUR_EMAIL'
gmail_password = 'ENTER_YOUR_PASSWORD'
# Create a message container
msg = MIMEMultipart()
msg['From'] = gmail_user
msg['To'] = EMAIL_ID
msg['Subject'] = 'Event Ticket'
# Add text to the email body
text = MIMEText(f"Hey {PER_NAME},"
"\nPFA of your event Ticket"
"\nWe hope you enjoy the event!")
msg.attach(text)
# Add a pdf attachment to the email
fileName = f"{PER_NAME}_ticket.pdf"
with open(fileName, 'rb') as f:
pdf = MIMEApplication(f.read(), _subtype='pdf')
pdf.add_header('content-disposition', 'attachment', filename=os.path.basename(fileName))
msg.attach(pdf)
# Create the SMTP server and send the email
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(gmail_user, gmail_password)
server.send_message(msg)
server.quit()
This is where we add our mailing details. The biggest advantage is that our emails won’t go into spam.
A few issues you can face while sending mail:
- smtplib.SMTPAuthenticationError
- smtplib.smtpserverdisconnected connection unexpectedly closed
You can solve them by following this tutorial https://tinyurl.com/smtplib.
Also, if you add another for loop, you can avoid sending tickets to people with failed payment status on Razorpay.
Things left to do:
- Create a front end and host it
- Create a QR Code scanner and record the entry timings of attendees.
- Use it on an upcoming event