Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # mis imports
- import os
- from typing import List, Optional
- # flask imports
- from flask import Flask, flash, redirect, render_template, url_for
- from flask_login import (LoginManager, UserMixin, current_user, login_required, login_user, logout_user)
- from flask_sqlalchemy import SQLAlchemy
- # forms
- from flask_wtf import FlaskForm
- from sqlalchemy import ForeignKey, String
- from sqlalchemy.orm import Mapped, mapped_column, relationship
- from wtforms import StringField, SubmitField
- from wtforms.validators import DataRequired
- basedir = os.path.abspath(os.path.dirname(__file__))
- # create the app
- app = Flask(__name__)
- login_manager = LoginManager(app)
- # create the extension'
- # requires you to login
- login_manager.login_view = 'login'
- db = SQLAlchemy()
- # configure the SQLite database, relative to the app instance folder
- app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///project.db"
- # initialize the app with the extension
- db.init_app(app)
- login_manager.init_app(app)
- app.config['SECRET_KEY'] = 'secret key'
- @login_manager.user_loader
- def load_user(id):
- return db.session.get(User, int(id))
- # models/tables
- user_books = db.Table(
- "user_books",
- db.metadata,
- db.Column("users_id", ForeignKey("user.id"), primary_key=True),
- db.Column("books_id", ForeignKey("books.id"), primary_key=True),
- )
- class User(UserMixin, db.Model):
- '''
- Many to Many relationship
- '''
- id: Mapped[int] = mapped_column(primary_key=True)
- # unique blocks the same username etc
- # I can't have Nullable=False because it will make me add the columns everytime I add a column in User table
- username: Mapped[str] = mapped_column(String(80), index=True, unique=True)
- rel_books: Mapped[List["Books"]] = relationship(secondary=user_books, back_populates="rel_user")
- def __repr__(self):
- return '<User {}>'.format(self.username)
- class Books(UserMixin, db.Model):
- '''
- Many to Many relationship
- '''
- id: Mapped[int] = mapped_column(primary_key=True)
- book_name: Mapped[str] = mapped_column(String(120)) # todo add unique=True for all users in a function
- chapter_name: Mapped[Optional[str]] = mapped_column(String(120))
- rel_user: Mapped[List["User"]] = relationship(secondary=user_books, back_populates="rel_books")
- def __repr__(self):
- return '<books {}>'.format(self.books_name)
- '''forms'''
- class CreateUserForm(FlaskForm):
- '''
- This is in the "/book/create" route.
- The form are book_name + book_chapters.
- '''
- username = StringField('username', validators=[DataRequired("The book's name is required")])
- submit = SubmitField('Submit')
- class CreateBookForm(FlaskForm):
- '''
- This is in the "/book/create" route.
- The form are book_name + book_chapters.
- '''
- book_name = StringField('book name', validators=[DataRequired("The book's name is required")])
- submit = SubmitField('Submit')
- # add user
- @app.route('/', methods = ['GET', 'POST'])
- @app.route('/home', methods = ['GET', 'POST'])
- def home():
- form = CreateUserForm()
- if form.validate_on_submit():
- username_form = form.username.data
- user_db = User(username=username_form)
- flash(f'user_db from User= {user_db}')
- db.session.add(user_db)
- db.session.commit()
- user_db = db.session.execute(db.select(User).filter_by(username=username_form)).scalar_one_or_none()
- flash(f'user_db={user_db}')
- if user_db != None:
- flash('login successfull!!')
- login_user(user_db)
- return redirect(url_for('create_book'))
- else:
- flash('login unsucessful')
- return render_template('home.html', form=form)
- # create book
- @app.route('/book/create', methods = ['GET', 'POST'])
- @login_required
- def create_book():
- form = CreateBookForm()
- if form.validate_on_submit():
- book_name_form = form.book_name.data
- user_db = db.session.execute(db.select(User).filter_by(username=current_user.username)).scalar_one_or_none()
- users_db = db.session.scalars(db.select(User)).all()
- flash(f'users_db{users_db}')
- # create a connection between the user and the book
- add_book_info = Books(book_name=book_name_form)
- user_db.rel_books.append(add_book_info)
- db.session.add(add_book_info)
- db.session.commit()
- user_db = db.session.execute(db.select(User).filter_by(username=current_user.username)).scalar_one_or_none()
- flash(f'user_db={user_db}')
- # Get books_db from the user_db column by using the relationship column in the table.
- books_db = user_db.rel_books
- for book_db in books_db:
- flash(book_db.book_name)
- book_db = db.session.execute(db.select(Books).filter_by(book_name=book_name_form)).scalar_one_or_none()
- '''
- The line below does not work no matter what.
- flash(f'book_db={book_db}')
- '''
- # Get users_db from the book_db column by using the relationship column in the table.
- users_db = book_db.rel_user
- # normally I would use user_db but to make the code clearer I changed the name.
- for db_user in users_db:
- flash(db_user.username) # this line will work
- #books_db = db.session.scalars(db.select(Books)).all()
- #flash(f'books_db={books_db}')
- flash('You have created a book successfully')
- return render_template('create_book.html', title='create book', form=form)
- @app.route("/logout")
- @login_required
- def logout():
- logout_user()
- return redirect(url_for('home'))
- # testing FormField or put simply testing many forms
- from wtforms import FieldList, FormField
- from sqlalchemy import select, func
- class UsernameForms(FlaskForm):
- usernames = FieldList(FormField(CreateUserForm), min_entries=0, max_entries=0)
- @app.route('/usernames', methods=['GET', 'POST'])
- def usernames():
- # Get the number of usernames in the database
- number_of_usernames_in_db = db.session.scalar(select(func.count(User.username)))
- flash(number_of_usernames_in_db)
- # Initialize the form with max_entries set to the number of emails
- form = UsernameForms()
- form.usernames.max_entries = number_of_usernames_in_db # Set max_entries
- if form.validate_on_submit():
- pass
- return render_template('usernames.html', form=form)
- if __name__ == '__main__':
- app.run(debug=True)
Advertisement
Add Comment
Please, Sign In to add comment