9-5:図書館賃貸サービス(個人項目)


[アリスAIコース]9週目-5
  • Rentテーブルアーキテクチャ構想と作成(MySQL,Python sqlalchemy)
  • リース機能実施
  • 返却ページ実施
  • 返却機能
  • を実施する.
  • Rentテーブルアーキテクチャ構想と作成(MySQL、Flask sqlalchemy)
    mysql> create table `rent_tb`(
        -> _id int primary key auto_increment not null,
        -> user_id int not null,
        -> book_id int not null,
        -> rent_date date,
        -> due_date date,
        -> foreign key(user_id) references user_tb(_id) on update cascade,
        -> foreign key(book_id) references books_tb(_id) on update cascade);
    Query OK, 0 rows affected (0.30 sec)

  • maria dbはrent_date date default current_dateの形式で指定すればよいという文章を見て、試してみましたが、エラーが発生しました.
    ( https://stackoverflow.com/questions/20461030/current-date-curdate-not-working-as-default-date-value )
    mysqlのデータ挿入当日のデフォルト設定方法もグーグルでは不明なので、個別にデフォルト値を設定していません.まず、MySQL CLIを直接使用するのではなく、Flask上で行うため、データ挿入が可能です.
    # models.py
    
    class User(db.Model):
        __tablename__ = 'user_tb'
        _id = db.Column(db.Integer,  primary_key=True,
                       nullable=False, autoincrement=True)
        name = db.Column(db.String(20), nullable=False)
        email = db.Column(db.String(30), nullable=False, unique=True)
        pw = db.Column(db.String(200), nullable=False)
    
        renter = db.relationship("Rent", backref='user_tb')
    
        def __init__(self, user_name, user_email, user_pw):
            self.name = user_name
            self.email = user_email
            self.pw = user_pw
    
    class Rent(db.Model):
        __tablename__='rent_tb'
        _id = db.Column(db.Integer, primary_key=True, nullable=False, autoincrement=True)
        user_id = db.Column(db.Integer, db.ForeignKey('user_tb._id'), nullable=False)
        book_id = db.Column(db.Integer, db.ForeignKey('books_tb._id'), nullable=False)
        rent_date = db.Column(db.Date, default=date.today)
        due_date = db.Column(db.Date, default=date.today()+timedelta(days=14))
        return_date = db.Column(db.Date)
    
        def __init__(self, user_id, book_id):
            self.user_id = user_id
            self.book_id = book_id

  • このコードを書く前に、多くのエラーとグーグル化を経験しました.sqlalchemyで外部キーを設定する方法がよく分からないので、時間がかかりました.検索時db.ForeignKey、ForeignKey、Forein Keyなど似たようなコードがたくさん出てきましたが、それだけを設定するのではなく、引用されたテーブルに関係を設定します.renter = db.relationship("Rent", backref='user_tb')そうです!!カッコには、参照されたテーブル、参照されたテーブルの実際のdb上の名前が含まれます.→Ellis 11/11日のリアルタイムレッスンコードを参考にしました.また、Rentテーブルに外部キーを設定する場合はnullable=Falseを最後にしておく必要があります.これによりエラーは発生しません.(前に発生したエラー:https://stackoverflow.com/questions/59626077/positional-argument-after-keyword-argument-and-regular-parameter-after-paramet)

  • 満期日を14日後に設定したいです.これはdateとtimedeltaの加算によって解決できる.(参照:https://wangin9.tistory.com/entry/datetime)
  • リース機能を実現
    function rentBook(bookId){
    
            let renter = `{{g.user._id}}`
    
            $.ajax({
                url: '/rent',
                type: 'patch',
                data: {
                    'book_id': bookId,
                    'renter': renter,
                },
                success: function (res){
                    let result = res['result']
                    if (result == "success") {
                        alert("대여 완료!")
                        window.location.reload()
                    } else if (result == "disable") {
                        alert("현재 대여가 불가능한 책입니다.")
                    } else {
                        alert("문제가 생겼어요. 다시 시도해 주세요.")
                    }
                }
            });
    @board.route("/rent", methods=["PATCH"])
    def rent():
        book_id = request.form['book_id']
        book = Books.query.filter(Books._id==book_id).first()
        if book.stock > 0:
            book.stock -= 1
            db.session.commit()
    
            user_id = request.form['renter']
            rent = Rent(user_id, book._id)
            db.session.add(rent)
            db.session.commit()
            return jsonify({"result": "success"})
        return jsonify({"result": "disable"})
  • 2<a href="#" onclick="rentBook('{{ book._id }}'); return false;" class="btn btn-primary">대여하기</a>でリース」ボタンをクリックしてrentBook関数を実行します.return false;を貼り付け、href接続のリンクに移動しないようにします.(注:https://ggmouse.tistory.com/418)rentBook関数から図書idと借用者を渡し、新しい値としてRentテーブルに入れる.ライブラリを確認し、1の作業を処理します.
  • これは,
  • 返却ページ実現返却ページホームページとほぼ同様の形態である.しかし,ここで厄介な部分は,ユーザが本を借りる画像,書名,本を借りる日付を示すことであり,これは複数の表に分かれた情報である.そのためormクエリの作成は少し困難です.しかしrecords = db.session.query(Books.img_path, Books.book_name, Books._id, Rent.rent_date).filter(Books._id==Rent.book_id, Rent.user_id==g.user._id, Rent.return_date==None).all()はこのように解決した.
    (sqlalchemyに関する参考記事:https://lowelllll.github.io/til/2019/04/19/TIL-flask-sqlalchemy-orm/)
  • 返却機能を押して返却ボタンを実現すると、Rentテーブルに保存されているデータのうち、そのユーザが借りた本の返却日を今日に更新しなければならない.Flaskで処理されているのに(datetimeライブラリのdate.today()を使用)dbでどのように確認してもnull値なので、うろうろしているうちに原因が見つかりました.db.session.commit()はやったことがありません...バカみたいなミスですが、起こり得るミスは、これから気をつけます.
  • これまでの結果
    https://oceanic-sesame-1f5.notion.site/434d494e42fe494093d764d7e64ba6c7