Improved the previously created Line bot that draws an arbitrary date on a photo, saves the name and date of birth in the database, and how old it is from the shooting date I created a linebot that calculates the photo or writes it to the image. Click here for github
・ Growth record assistant (ID: @ 033cynwe)
--LineBot channel creation --Deploy to heroku
main.py
from flask import Flask, request, abort
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import (FollowEvent, PostbackEvent, TemplateSendMessage, MessageAction,\
ButtonsTemplate, DatetimePickerTemplateAction, ImageMessage, \
ImageSendMessage, MessageEvent, TextMessage, TextSendMessage)
from pathlib import Path
from PIL import Image, ImageDraw, ImageFont, ImageFilter
import datetime
import os
import database
app = Flask(__name__)
app.debug = False
#Get environment variables
YOUR_CHANNEL_ACCESS_TOKEN = os.environ["YOUR_CHANNEL_ACCESS_TOKEN"]
YOUR_CHANNEL_SECRET = os.environ["YOUR_CHANNEL_SECRET"]
line_bot_api = LineBotApi(YOUR_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(YOUR_CHANNEL_SECRET)
#Image referrer path
SRC_IMAGE_PATH = "static/images/{}.jpg "
MAIN_IMAGE_PATH = "static/images/{}_main.jpg "
PREVIEW_IMAGE_PATH = "static/images/{}_preview.jpg "
@app.route("/callback", methods=['POST'])
def callback():
signature = request.headers['X-Line-Signature']
body = request.get_data(as_text=True)
app.logger.info("Request body: " + body)
try:
handler.handle(body, signature)
except InvalidSignatureError:
abort(400)
return 'OK'
#Follow event
@handler.add(FollowEvent)
def handle_follow(event):
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text=
"Thank you for registering as a friend. I'll write in the image how old the person in the picture is. Please send me an image."))
#Receiving images
@handler.add(MessageEvent, message=ImageMessage)
def handle_image(event):
global message_id, user_id, name_list, user_dict, num, src_image_path
#List for storing user information
name_list = []
day_list = []
user_dict = {}
#message_Get id
message_id = event.message.id
#user_Get id
user_id = event.source.user_id
#File name message_Path converted to id
src_image_path = Path(SRC_IMAGE_PATH.format(message_id)).absolute()
#Temporarily save images to Heroku
save_image(message_id, src_image_path)
#Check user information and pass if not registered
try:
name_list, day_list = database.serch_data(user_id)
except TypeError:
pass
#Registration number
num = len(name_list)
#If not registered, check your name
if num == 0:
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text="What is the name of the person in the photo?"))
#user_Add id
database.add_data(user_id)
#If you have a registration, check who is in the picture
elif num != 0:
#Create a dictionary with name and day
user_dict = dict(zip(name_list, day_list))
#When registering one person
if num == 1:
name_1 = name_list[0]
buttons_template = TemplateSendMessage(
alt_text="Who is in the picture?",
template=ButtonsTemplate(
text="Who is in the picture?", actions=[
MessageAction(label=name_1, text=name_1),
MessageAction(label="Other", text="Other")
]
)
)
#In case of 2 person registration
elif num == 2:
name_1 = name_list[0]
name_2 = name_list[1]
buttons_template = TemplateSendMessage(
alt_text="Who is in the picture?",
template=ButtonsTemplate(
text="Who is in the picture?", actions=[
MessageAction(label=name_1, text=name_1),
MessageAction(label=name_2, text=name_2),
MessageAction(label="Other", text="Other")
]
)
)
#In case of 3 person registration
elif num == 3:
name_1 = name_list[0]
name_2 = name_list[1]
name_3 = name_list[2]
buttons_template = TemplateSendMessage(
alt_text="Who is in the picture?",
template=ButtonsTemplate(
text="Who is in the picture?", actions=[
MessageAction(label=name_1, text=name_1),
MessageAction(label=name_2, text=name_2),
MessageAction(label=name_3, text=name_3),
MessageAction(label="Other", text="Other")
]
)
)
line_bot_api.reply_message(event.reply_token, buttons_template)
#Receiving text
@handler.add(MessageEvent, message=TextMessage)
def handle_text(event):
global text_name, birthday
#Confirmation of date of birth if not registered
if num == 0:
text_name = event.message.text
select_day(event)
#If other is selected, check the name
elif event.message.text == "Other":
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text="What is the name of the person in the photo?"))
else:
text_name = event.message.text
#If the name is already registered, get the date of birth
if text_name in name_list:
birthday = user_dict[text_name]
#If if, select the shooting date, otherwise select the date of birth
select_day(event)
#Process and send images
@handler.add(PostbackEvent)
def handle_postback(event):
global birthday
#File name message_Path converted to id
main_image_path = MAIN_IMAGE_PATH.format(message_id)
preview_image_path = PREVIEW_IMAGE_PATH.format(message_id)
#If birthday is undefined
if not "birthday" in globals():
#Substitute the result of the date selection action for birthday
birthday = event.postback.params["date"]
#Update name and day
database.update_data(user_id, num, text_name, birthday)
#Selection of shooting date
select_day(event)
#If birthday is defined
elif "birthday" in globals():
#Image processing
date_the_image(src_image_path, Path(main_image_path).absolute(), event)
date_the_image(src_image_path, Path(preview_image_path).absolute(), event)
#Specify image
image_message = ImageSendMessage(
original_content_url=f"https://<heroku app name>.herokuapp.com/{main_image_path}",
preview_image_url=f"https://<heroku app name>.herokuapp.com/{preview_image_path}"
)
#Get log
app.logger.info(f"https://<heroku app name>.herokuapp.com/{main_image_path}")
#Send image
line_bot_api.reply_message(event.reply_token, image_message)
#Delete the variable birthday
del birthday
#Save database changes and disconnect
database.close_db()
#Image storage function
def save_image(message_id: str, save_path: str) -> None:
# message_Get binary data of image from id
message_content = line_bot_api.get_message_content(message_id)
with open(save_path, "wb") as f:
#Write the acquired binary data
for chunk in message_content.iter_content():
f.write(chunk)
#Date selection function
def select_day(event):
#If birthday is defined
if "birthday" in globals():
message = "Please select the shooting date"
#If birthday is undefined
elif not "birthday" in globals():
message = "Please select your date of birth"
#Date selection action
date_picker = TemplateSendMessage(
alt_text=message,
template=ButtonsTemplate(
text=message,
actions=[
DatetimePickerTemplateAction(
label="Choice",
data="action=buy&itemid=1",
mode="date",
initial=str(datetime.date.today()),
max=str(datetime.date.today())
)
]
)
)
line_bot_api.reply_message(event.reply_token, date_picker)
#Image processing function
def date_the_image(src: str, desc: str, event) -> None:
im = Image.open(src)
draw = ImageDraw.Draw(im)
font = ImageFont.truetype("./fonts/AquaKana.ttc", 50)
#Get the shooting date
date = event.postback.params["date"]
#Calculate the number of days after birth by subtracting the date of birth from the shooting date
how_old = datetime.datetime.strptime(date, "%Y-%m-%d") - datetime.datetime.strptime(str(birthday), "%Y-%m-%d")
#Days of birth and 365(Day)Calculate quotient and remainder with
years, days = divmod(how_old.days, 365)
#Remainder 30(Day)Calculate quotient with
month = days // 30
text = text_name + f"({years}Talent{month}months)"
#Text size
text_width = draw.textsize(text, font=font)[0]
text_height = draw.textsize(text, font=font)[1]
margin = 10
x = im.width - text_width
y = im.height - text_height
#The size of the rectangle to draw
rect_size = ((text_width + margin * 6), (text_height + margin * 2))
#Rectangle drawing
rect = Image.new("RGB", rect_size, (0, 0, 0))
#Mask to make the rectangle transparent
mask = Image.new("L", rect_size, 128)
#Paste the rectangle and mask on the image
im.paste(rect, (x - margin * 6, y - margin * 3), mask)
#Writing text
draw.text((x - margin * 3, y - margin * 2), text, fill=(255, 255, 255), font=font)
im.save(desc)
if __name__ == "__main__":
#app.run()
port = int(os.getenv("PORT", 5000))
app.run(host="0.0.0.0", port=port)
database.py
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import create_engine, Column, String, Date
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session
from sqlalchemy.orm.exc import NoResultFound
import datetime
import os
#Get the database URL from an environment variable
DATABASE_URL = os.environ["DATABASE_URL"]
engine = create_engine(DATABASE_URL)
Base = declarative_base()
#table definition
class User(Base):
__tablename__ = "user_list"
user_id = Column("user_id", String(50), primary_key=True)
name1 = Column("name1", String(10))
day1 = Column("day1", Date)
name2 = Column("name2", String(10))
day2 = Column("day2", Date)
name3 = Column("name3", String(10))
day3 = Column("day3", Date)
Base.metadata.create_all(engine)
session = Session(bind=engine)
#user_id search
def serch_data(user_id):
try:
#user_Search by id
res = session.query(User.name1, User.day1, User.name2, User.day2, User.name3, User.day3).filter(User.user_id==f"{user_id}").one()
#Insert name and day into the list respectively
name_list = [n for n in res if type(n) is str]
day_list = [str(d) for d in res if type(d) is datetime.date]
return name_list, day_list
#user_Pass if id is not registered
except NoResultFound:
pass
#user_id registration
def add_data(user_id):
session.add(User(user_id=f"{user_id}"))
#Update user information
def update_data(user_id, num, text_name, birthday):
user_data = session.query(User).filter(User.user_id==f"{user_id}").one()
#Save name and day according to the number of registrations
if num == 0:
user_data.name1 = text_name
user_data.day1 = birthday
elif num == 1:
user_data.name2 = text_name
user_data.day2 = birthday
elif num == 2:
user_data.name3 = text_name
user_data.day3 = birthday
#Save database changes and disconnect
def close_db():
session.commit()
session.close()
main.py
main.py
from flask import Flask, request, abort
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import (FollowEvent, PostbackEvent, TemplateSendMessage, MessageAction,\
ButtonsTemplate, DatetimePickerTemplateAction, ImageMessage, \
ImageSendMessage, MessageEvent, TextMessage, TextSendMessage)
from pathlib import Path
from PIL import Image, ImageDraw, ImageFont, ImageFilter
import datetime
import os
import database
app = Flask(__name__)
app.debug = False
#Get environment variables
YOUR_CHANNEL_ACCESS_TOKEN = os.environ["YOUR_CHANNEL_ACCESS_TOKEN"]
YOUR_CHANNEL_SECRET = os.environ["YOUR_CHANNEL_SECRET"]
line_bot_api = LineBotApi(YOUR_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(YOUR_CHANNEL_SECRET)
#Image referrer path
SRC_IMAGE_PATH = "static/images/{}.jpg "
MAIN_IMAGE_PATH = "static/images/{}_main.jpg "
PREVIEW_IMAGE_PATH = "static/images/{}_preview.jpg "
@app.route("/callback", methods=['POST'])
def callback():
signature = request.headers['X-Line-Signature']
body = request.get_data(as_text=True)
app.logger.info("Request body: " + body)
try:
handler.handle(body, signature)
except InvalidSignatureError:
abort(400)
return 'OK'
Import the module and get the environment variables set in advance, but I hope you can check the detailed role as appropriate.
Set the path of the image reference source described later, and replace the {}
part with the message_id
when the image was received.
main.py
#Follow event
@handler.add(FollowEvent)
def handle_follow(event):
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text=
"Thank you for registering as a friend. I'll write in the image how old the person in the picture is. Please send me an image."))
A message is sent when a user adds a friend.
main.py
#Receiving images
@handler.add(MessageEvent, message=ImageMessage)
def handle_image(event):
global message_id, user_id, name_list, user_dict, num, src_image_path
#List for storing user information
name_list = []
day_list = []
user_dict = {}
#message_Get id
message_id = event.message.id
#user_Get id
user_id = event.source.user_id
#File name message_Path converted to id
src_image_path = Path(SRC_IMAGE_PATH.format(message_id)).absolute()
#Temporarily save images to Heroku
save_image(message_id, src_image_path)
#Check user information and pass if not registered
try:
name_list, day_list = database.serch_data(user_id)
except TypeError:
pass
#Registration number
num = len(name_list)
#If not registered, check your name
if num == 0:
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text="What is the name of the person in the photo?"))
#user_Add id
database.add_data(user_id)
#If you have a registration, check who is in the picture
elif num != 0:
#Create a dictionary with name and day
user_dict = dict(zip(name_list, day_list))
#When registering one person
if num == 1:
name_1 = name_list[0]
buttons_template = TemplateSendMessage(
alt_text="Who is in the picture?",
template=ButtonsTemplate(
text="Who is in the picture?", actions=[
MessageAction(label=name_1, text=name_1),
MessageAction(label="Other", text="Other")
]
)
)
#In case of 2 person registration
elif num == 2:
name_1 = name_list[0]
name_2 = name_list[1]
buttons_template = TemplateSendMessage(
alt_text="Who is in the picture?",
template=ButtonsTemplate(
text="Who is in the picture?", actions=[
MessageAction(label=name_1, text=name_1),
MessageAction(label=name_2, text=name_2),
MessageAction(label="Other", text="Other")
]
)
)
#In case of 3 person registration
elif num == 3:
name_1 = name_list[0]
name_2 = name_list[1]
name_3 = name_list[2]
buttons_template = TemplateSendMessage(
alt_text="Who is in the picture?",
template=ButtonsTemplate(
text="Who is in the picture?", actions=[
MessageAction(label=name_1, text=name_1),
MessageAction(label=name_2, text=name_2),
MessageAction(label=name_3, text=name_3),
MessageAction(label="Other", text="Other")
]
)
)
line_bot_api.reply_message(event.reply_token, buttons_template)
Specify the variable you want to use other than MessageEvent in global
so that it can be referenced.
In the try statement name_list, day_list = database.serch_data (user_id)
, the name_list
that stores the name and the day_list
that stores the date of birth are obtained by the serch_data
function of the database
file. Update to.
At this time, if user_id is not registered, no value is returned and it cannot be updated, so specify TypeError
in except.
As a result of referring to the data, the processing is divided depending on whether there is no registration or not.
If not, check the name and add user_id.
If there is, use ʻuser_dict = dict (zip (name_list, day_list))to create a dictionary to refer to the date of birth using the name as a key. After that, the process is further divided by 1 to 3 registered people, and the person in the picture is confirmed by
TemplateSendMessage`.
main.py
#Receiving text
@handler.add(MessageEvent, message=TextMessage)
def handle_text(event):
global text_name, birthday
#Confirmation of date of birth if not registered
if num == 0:
text_name = event.message.text
select_day(event)
#If other is selected, check the name
elif event.message.text == "Other":
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text="What is the name of the person in the photo?"))
else:
text_name = event.message.text
#If the name is already registered, get the date of birth
if text_name in name_list:
birthday = user_dict[text_name]
#If if, select the shooting date, otherwise select the date of birth
select_day(event)
ʻIf num == 0:` is executed when you receive a reply that confirms the name when there is no registration, and proceeds to confirm the date of birth after obtaining the name.
ʻElif event.message.text ==" Other ":is executed when Other is selected in
TemplateSendMessage` when there is registration, and confirms the name.
ʻElse:is executed when a registered name is selected in
TemplateSendMessageother than the above, and when a reply is received after confirming the name. If you have already registered, use
birthday = user_dict [text_name]` to get the date of birth using the name as a key.
For other replies, proceed to date selection and ask them to select their date of birth.
main.py
#Process and send images
@handler.add(PostbackEvent)
def handle_postback(event):
global birthday
#File name message_Path converted to id
main_image_path = MAIN_IMAGE_PATH.format(message_id)
preview_image_path = PREVIEW_IMAGE_PATH.format(message_id)
#If birthday is undefined
if not "birthday" in globals():
#Substitute the result of the date selection action for birthday
birthday = event.postback.params["date"]
#Update name and day
database.update_data(user_id, num, text_name, birthday)
#Selection of shooting date
select_day(event)
#If birthday is defined
elif "birthday" in globals():
#Image processing
date_the_image(src_image_path, Path(main_image_path).absolute(), event)
date_the_image(src_image_path, Path(preview_image_path).absolute(), event)
#Specify image
image_message = ImageSendMessage(
original_content_url=f"https://<heroku app name>.herokuapp.com/{main_image_path}",
preview_image_url=f"https://<heroku app name>.herokuapp.com/{preview_image_path}"
)
#Get log
app.logger.info(f"https://<heroku app name>.herokuapp.com/{main_image_path}")
#Send image
line_bot_api.reply_message(event.reply_token, image_message)
#Delete the variable birthday
del birthday
#Save database changes and disconnect
database.close_db()
ʻIf not "birthday" in globals (): does what happens when birthday is undefined (the date of birth was selected by the date selection action). Get the date selected by
birthday = event.postback.params [" date "]and update the database name and date of birth with
database.update_data (user_id, num, text_name, birthday)` , Ask them to select the shooting date.
ʻElif" birthday "in globals ():Performs processing when birthday is defined (the shooting date was selected by the date selection action).
image_message = ImageSendMessage(
original_content_url = f "https: //
Delete the variable birthday with del birthday
so that it can be processed normally even when images are sent continuously.
Finally, save the database changes with close_db ()
in the database file, disconnect and exit.
main.py
#Image storage function
def save_image(message_id: str, save_path: str) -> None:
# message_Get binary data of image from id
message_content = line_bot_api.get_message_content(message_id)
with open(save_path, "wb") as f:
#Write the acquired binary data
for chunk in message_content.iter_content():
f.write(chunk)
Actually, I wanted to get the Exif information of the image and automatically enter the shooting date, but I could not get it with this method, so I took the form of the above date selection action as a painstaking measure. If anyone knows how to do it, please let me know.
main.py
#Date selection function
def select_day(event):
#If birthday is defined
if "birthday" in globals():
message = "Please select the shooting date"
#If birthday is undefined
elif not "birthday" in globals():
message = "Please select your date of birth"
#Date selection action
date_picker = TemplateSendMessage(
alt_text=message,
template=ButtonsTemplate(
text=message,
actions=[
DatetimePickerTemplateAction(
label="Choice",
data="action=buy&itemid=1",
mode="date",
initial=str(datetime.date.today()),
max=str(datetime.date.today())
)
]
)
)
line_bot_api.reply_message(event.reply_token, date_picker)
This function is executed once if the date of birth is registered, and twice in total if it is not registered. Therefore, if birthday is defined, the message will be changed to the shooting date, and if it is not defined, the message will be changed to the date of birth.
main.py
#Image processing function
def date_the_image(src: str, desc: str, event) -> None:
im = Image.open(src)
draw = ImageDraw.Draw(im)
font = ImageFont.truetype("./fonts/AquaKana.ttc", 50)
#Get the shooting date
date = event.postback.params["date"]
#Calculate the number of days after birth by subtracting the date of birth from the shooting date
how_old = datetime.datetime.strptime(date, "%Y-%m-%d") - datetime.datetime.strptime(str(birthday), "%Y-%m-%d")
#Days of birth and 365(Day)Calculate quotient and remainder with
years, days = divmod(how_old.days, 365)
#Remainder 30(Day)Calculate quotient with
month = days // 30
text = text_name + f"({years}Talent{month}months)"
#Text size
text_width = draw.textsize(text, font=font)[0]
text_height = draw.textsize(text, font=font)[1]
margin = 10
x = im.width - text_width
y = im.height - text_height
#The size of the rectangle to draw
rect_size = ((text_width + margin * 6), (text_height + margin * 2))
#Rectangle drawing
rect = Image.new("RGB", rect_size, (0, 0, 0))
#Mask to make the rectangle transparent
mask = Image.new("L", rect_size, 128)
#Paste the rectangle and mask on the image
im.paste(rect, (x - margin * 6, y - margin * 3), mask)
#Writing text
draw.text((x - margin * 3, y - margin * 2), text, fill=(255, 255, 255), font=font)
im.save(desc)
Specify the font and size to draw with font = ImageFont.truetype ("./fonts/AquaKana.ttc", 50)
.
When drawing Japanese, some fonts are not supported, so select one that contains Japanese in the preview.
Get the shooting date with date = event.postback.params [" date "]
and how_old = datetime.datetime.strptime (date,"% Y-% m-% d ") --datetime.datetime.strptime ( Use str (birthday), "% Y-% m-% d")
to get the number of days obtained by subtracting the date of birth from the shooting date.
Calculate the quotient and remainder by dividing the number of days by 365 (days) with years, days = divmod (how_old.days, 365)
, and substitute the age for years and the number of days for the remainder for days.
month = days // 12
converts the remaining days to months, andtext = text_name + f "({years} years {month} months)"
defines what to write.
Use rect_size = ((text_width + margin * 6), (text_height + margin * 2))
to set the size of the rectangle and mask, and leave a margin of 30px on the left and right and 10px on the top and bottom of the text.
Finally, specify the position of the rectangle and mask with ʻim.paste (rect, (x --margin * 6, y --margin * 3), mask) and paste it, and
draw.text ( Write the text with (x --margin * 3, y --margin * 2), text, fill = (255, 255, 255), font = font) `and you're done.
main.py
if __name__ == "__main__":
#app.run()
port = int(os.getenv("PORT", 5000))
app.run(host="0.0.0.0", port=port)
database.py
database.py
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import create_engine, Column, String, Date
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session
from sqlalchemy.orm.exc import NoResultFound
import datetime
import os
#Get the database URL from an environment variable
DATABASE_URL = os.environ["DATABASE_URL"]
engine = create_engine(DATABASE_URL)
Base = declarative_base()
First, import the required modules in the database file.
DATABASE_URL specifies the database URL set in heroku config
.
ʻEngine = create_engine (DATABASE_URL) ,
Base = declarative_base () `is used for the next table creation.
database.py
#table definition
class User(Base):
__tablename__ = "user_list"
user_id = Column("user_id", String(50), primary_key=True)
name1 = Column("name1", String(10))
day1 = Column("day1", Date)
name2 = Column("name2", String(10))
day2 = Column("day2", Date)
name3 = Column("name3", String(10))
day3 = Column("day3", Date)
Base.metadata.create_all(engine)
session = Session(bind=engine)
In class User (Base):
, specify the table name and column contents only at the time of creation.
At this time, it is necessary to specify primary_key in some column, so specify it in a column that does not cause duplication.
Prepare to connect to the database with Base.metadata.create_all (engine)
, session = Session (bind = engine)
.
database.py
#user_id search
def serch_data(user_id):
try:
#user_Search by id
res = session.query(User.name1, User.day1, User.name2, User.day2, User.name3, User.day3).filter(User.user_id==f"{user_id}").one()
#Insert name and day into the list respectively
name_list = [n for n in res if type(n) is str]
day_list = [str(d) for d in res if type(d) is datetime.date]
return name_list, day_list
#user_Pass if id is not registered
except NoResultFound:
pass
res = session.query (User.name1, User.day1, User.name2, User.day2, User.name3, User.day3) .filter (User.user_id == f" {user_id} "). one () Gets information other than the user_id of the line where the user_id matches with
.
Since user_id cannot be duplicated, specify only one with ʻone () `.
name_list = [n for n in res if type (n) is str]
to change str type (name) to name_list, day_list = [str (d) for d in res if type (d) is datetime.date] Insert datetime.date type (date of birth) into day_list as a string with
.
When you get the information with res
, the empty column gets None, but it doesn't apply to either of the above types, so you don't need ʻif ~ is not None. Returns two lists with
return name_list, day_list` and updates the list in main.py.
If user_id is not registered in res, it will be NoResultFound, so specify it with except to avoid it.
database.py
#user_id registration
def add_data(user_id):
session.add(User(user_id=f"{user_id}"))
#Update user information
def update_data(user_id, num, text_name, birthday):
user_data = session.query(User).filter(User.user_id==f"{user_id}").one()
#Save name and day according to the number of registrations
if num == 0:
user_data.name1 = text_name
user_data.day1 = birthday
elif num == 1:
user_data.name2 = text_name
user_data.day2 = birthday
elif num == 2:
user_data.name3 = text_name
user_data.day3 = birthday
If user_id is not registered in session.add (User (user_id = f" {user_id} "))
, it will be added.
ʻUser_data = session.query (User) .filter (User.user_id == f "{user_id}"). Get user information with one () `, branch with if and update the appropriate column. At this time, I tried to get and update only the necessary columns, but an error occurred, so it seems safer to get all the information.
database.py
#Save database changes and disconnect
def close_db():
session.commit()
session.close()
Save the database changes with session.commit ()
and disconnect with session.close ()
to finish.
About two months after last completion, I managed to incorporate the database I was dealing with for the first time to the point I was aiming for. On the way, I tried new things such as changing from MySQL to PostgreSQL and using sqlalchemy that I did not plan to use at the beginning, but I was able to implement it relatively smoothly compared to the previous time, and I could feel a slight growth. ..
For this bot, I would like to complete it once and create an application that improves inconveniences when I have time.
-How to use PostgreSQL pgAdmin 4 (Refer data from startup) -[[Python ORM] Summary of basic SQL queries with SQLAlchemy](https://qiita.com/tomo0/items/a762b1bc0f192a55eae8#select%E3%82%AB%E3%83%A9%E3%83%A0 % E3% 82% 92% E6% 8C% 87% E5% AE% 9A) -[Create a web app with Flask and PostgreSQL and run it for free on Heroku](https://qiita.com/croquette0212/items/9b4dc5377e7d6f292671#heroku%E3%81%ABdeploy%E3%81%99%E3%82 % 8B)
Recommended Posts