im learning about Flask and flask-sqlalchemy relationships. I have five tables Clientes, Solicitud, Cotizacion, Servicio, Asesor. Im trying to get Service cost for a specific Request (Solicitud) table but i dont get it, why i cant get this value for a specific id Request (Solicitud) in crearcotizacion view. The process is like this: A client is created, then a Service and a Asesor(Advisor) is created. Then in crearsolicitudes view, all clients are listed, click on crear solicitud plus button, and then the create request form appears, the data of the client and request all ok. When i try to create a new quotation (cotizacion) crearcotizacion view, i cant bring the cost of the service value that belongs to that request and service. I try to create a foreing key between request (Solicitud) and Servicio but it doesnt work.
My Model
class Clientes(db.Model):
__tablename__ = "clientes"
id = db.Column(db.Integer, primary_key=True)
nombres = db.Column(db.String(80), nullable=False)
apellidos = db.Column(db.String(80), nullable=False)
correo = db.Column(db.String(120), nullable=False)
empresa = db.Column(db.String(120), nullable=False)
celular = db.Column(db.String(50), nullable=False)
mensaje = db.Column(db.String(500), nullable=False)
checkbox = db.Column(db.Boolean, nullable=False)
cotizaciones = db.relationship('Cotizacion', backref='clientes_cotizan', lazy=True)
solicitudes = db.relationship('Solicitud', backref='sol_client', lazy=True)
servicios = db.relationship('Servicio', backref='clientes_servicios', lazy=True)
def __init__(self, nombres, apellidos, correo, empresa, celular, mensaje, checkbox, sol_client, clientes_servicios):
self.nombres = nombres
self.apellidos = apellidos
self.correo = correo
self.empresa = empresa
self.celular = celular
self.mensaje = mensaje
self.checkbox = checkbox
self.sol_client = sol_client
self.clientes_servicios = clientes_servicios
def __repr__(self):
return '<Clientes %r>' % self.id
class Solicitud(db.Model):
__tablename__ = "solicitud"
id = db.Column(db.Integer, primary_key=True)
servicio_campo = db.Column(db.String(120), nullable=False)
asesore = db.Column(db.String(120), nullable=False)
# LLAVE FORANEA
solicitud_cliente = db.Column(db.Integer, db.ForeignKey("clientes.id"), nullable=True)
solicitudes_cliente = db.relationship('Cotizacion', backref='clientes_solicitan', lazy=True)
solicitudes_servicio = db.relationship('Servicios', backref='solicitud_servicios', lazy=True)
def __init__(self, servicio_campo, asesore, sol_client, clientes_servicios):
self.servicio_campo = servicio_campo
self.asesore = asesore
self.sol_client = sol_client
self.clientes_servicios = clientes_servicios
class Cotizacion(db.Model):
__tablename__ = "cotizacion"
id = db.Column(db.Integer, primary_key=True)
numero_horas = db.Column(db.Integer, nullable=False)
descuento = db.Column(db.Integer, nullable=False)
valor_total = db.Column(db.Integer, nullable=False)
# LLAVE FORANEA
cliente_id = db.Column(db.Integer, db.ForeignKey("clientes.id"), nullable=True)
solicitud_id = db.Column(db.Integer, db.ForeignKey("solicitud.id"), nullable=True)
def __init__(self, numero_horas, descuento, valor_total, clientes_cotizan, clientes_solicitan):
self.numero_horas = numero_horas
self.descuento = descuento
self.valor_total = valor_total
self.clientes_cotizan = clientes_cotizan
self.clientes_solicitan = clientes_solicitan
def __repr__(self):
return '<Cotizacion %r>' % self.id
class Servicio(db.Model):
__tablename__ = "servicio"
id = db.Column(db.Integer, primary_key=True)
nombre_servicio = db.Column(db.String(120), nullable=False)
costo_servicio = db.Column(db.Integer, nullable=False)
# LLAVE FORANEA
cliente_id = db.Column(db.Integer, db.ForeignKey("clientes.id"), nullable=True)
solicitud_id = db.Column(db.Integer, db.ForeignKey("solicitud.id"), nullable=True)
def __init__(self, nombre_servicio, costo_servicio, clientes_servicios, solicitud_servicios):
self.nombre_servicio = nombre_servicio
self.costo_servicio = costo_servicio
self.clientes_servicios = clientes_servicios
self.solicitud_servicios = solicitud_servicios
class Asesor(db.Model):
__tablename__ = "asesor"
id = db.Column(db.Integer, primary_key=True)
primernombre_asesor = db.Column(db.String(120), nullable=False)
apellido_asesor = db.Column(db.String(120), nullable=False)
correo_asesor = db.Column(db.String(150), nullable=False)
def __init__(self, primernombre_asesor, apellido_asesor, correo_asesor, asesor_client):
self.primernombre_asesor = primernombre_asesor
self.apellido_asesor = apellido_asesor
self.correo_asesor = correo_asesor
self.asesor_client = asesor_client
My Views
#app.route('/cotizacion/crear/<int:id>', methods=("GET", "POST"))
#login_required
def crearcotizacion(id):
datos_solicitud = (db.session.query(Solicitud).filter_by(id=id).first())
datos_clientes = datos_solicitud.sol_client
datos_servicio = (db.session.query(Solicitud, Servicio.costo_servicio).join(Servicio).filter_by(id=id).first())
print(datos_servicio)
form = creacion_Cotizacion(request.form)
if current_user.role == True:
if request.method == 'POST':
cotizan = Cotizacion(
numero_horas=form.numero_horas.data,
descuento=form.descuento.data,
clientes_cotizan=datos_clientes,
clientes_solicitan=datos_solicitud,
clientes_servicios=datos_solicitud
)
db.session.add(cotizan)
db.session.commit()
flash('La cotización ha sido creado exitosamente', 'success')
return render_template('crearcotizacion.html', form=form, id=id, datos_solicitud=datos_solicitud, datos_clientes=datos_clientes, datos_servicio=datos_servicio)
else:
abort(401)
return render_template('crearcotizacion.html', nombres=current_user.nombres, correo=current_user.correo, role=current_user.role, id=id, form=form, datos_solicitud=datos_solicitud, datos_clientes=datos_clientes, datos_servicio=datos_servicio)
#app.route('/crearsolicitudes/crear/<int:id>', methods=("GET", "POST"))
#login_required
def crearsolicitud(id):
client = (db.session.query(Clientes).filter_by(id=id).one())
form = form_solicitudes(request.form)
datos_solicitud = (db.session.query(Solicitud).filter_by(id=id).first())
if current_user.role == True:
if request.method == 'POST':
solicitan = Solicitud(
servicio_campo = form.servicio_campo.data,
asesore = form.asesore.data,
sol_client = client,
clientes_servicios=datos_solicitud
)
db.session.add(solicitan)
db.session.commit()
message = f"La solicitud {solicitan.id} ha sido creada exitosamente"
flash(message, 'success')
return redirect(url_for('versolicitudes', client=client, id=id, form=form, nombres=current_user.nombres, correo=current_user.correo, role=current_user.role,))
else:
abort(401)
return render_template('crearsolicitudes.html', nombres=current_user.nombres, correo=current_user.correo, role=current_user.role, id=id, client=client, form=form)
#app.route('/crearcliente', methods=("GET", "POST"))
#login_required
def crearcliente():
clint = db.session.query(Clientes).filter_by(id=id).first()
form = creacion_Cliente(request.form)
client= Clientes(
nombres=form.nombres.data,
apellidos=form.apellidos.data,
correo=form.correo.data,
empresa=form.empresa.data,
celular=form.celular.data,
mensaje = form.mensaje.data,
checkbox = form.checkbox.data,
sol_client = clint,
clientes_servicios = clint)
if current_user.role == True:
if request.method == 'POST':
db.session.add(client)
db.session.commit()
message = f"El cliente {client.nombres} {client.apellidos} ha sido creado exitosamente"
flash(message, 'success')
return redirect(url_for('listarclientes', form=form))
else:
abort(401)
return render_template('crearcliente.html', form=form, nombres=current_user.nombres, correo=current_user.correo, role=current_user.role)
#app.route('/ver-solicitudes')
#login_required
def versolicitudes():
if current_user.role == True:
clientes= db.session.query(Solicitud.id, Solicitud.servicio_campo, Solicitud.asesore, Clientes.nombres, Clientes.apellidos, Clientes.correo, Clientes.empresa, Clientes.mensaje, Clientes.celular).join(Clientes).all()
return render_template('listacotizacion.html', clientes=clientes, nombres=current_user.nombres, correo=current_user.correo)
Related
I am programming an online auction using flask. And I settled on the following problem: I do not know how to check if the auction has ended. On the main page there is a selection of the first 6 lots from the database and on each product card there is an end timer that is updated when the page is refreshed, but when the time comes to an end, the time value goes into a negative value. It is required to implement the logic of constant checking of the end of all auctions available in the database.
The best thing I came up with is Apscheduler which checks all auctions from the database every 10 seconds, and if it finds a lot whose end time and current time difference is less than 0, then is_active=False is assigned to such a lot, but it seems to me not very optimal. What should I do?
ROUTES.PY
from flask import redirect, request, render_template, flash, g, send_from_directory
from werkzeug.security import check_password_hash, generate_password_hash
from flask_login import login_user, current_user, logout_user
import datetime as dt
import jwt
import os
from main_app import app, db, UserForm, AuctionLotForm, mail, a_lot_photos
from main_app.models import User, AuctionLotModel
#.strftime("%d-%m-%YT%H:%M")
#Главная страница
#app.route('/')
def main_page():
lots = AuctionLotModel.query.all()
cur_time = dt.datetime.now().replace(microsecond=0)
return render_template('main_page.html', lots=lots, cur_time=cur_time)
# Регистрация
#app.route('/registration', methods=["POST", "GET"])
def registration():
form = UserForm()
if form.validate_on_submit():
real_name = form.real_name.data
username = form.username.data
date_of_birth = form.date_of_birth.data
email = form.email.data
password = form.password.data
hashed_password = generate_password_hash(password)
user = User(real_name=real_name, username=username, date_of_birth=date_of_birth, email=email, password=hashed_password)
db.session.add(user)
db.session.commit()
login_user(user)
token = jwt.encode(
{'username':username},
app.config['SECRET_KEY'],
algorithm = 'HS256'
)
mail.send(
subject='Подтверждение почты',
receivers=[email],
html_template='auth/email_confirmation.html',
body_params={
"token": token
}
)
return render_template('auth/check_email.html')
return render_template('auth/registration.html', form=form)
#подтверждеие почты
#app.route('/email_verification/<token>')
def email_verification(token):
data = jwt.decode(token, app.config['SECRET_KEY'], algorithms=["HS256"])
username = data['username']
user = User.query.filter_by(username=username).one_or_404()
user.email_is_verified = True
db.session.commit()
return render_template('auth/email_is_confirmed.html')
#Форма авторизиции
#app.route('/login', methods=["POST", "GET"])
def login():
email = request.form.get('email')
password = request.form.get('password')
if request.method == 'POST':
if not (email and password):
flash('Заполните все поля')
else:
user = db.session.query(User).filter(User.email == email).first()
if not (user and check_password_hash(user.password, password)):
flash('Неверное имя пользователя или пароль')
else:
login_user(user)
return redirect('/')
return render_template('auth/login.html')
#Выход из профиля
#app.route('/logout', methods=["POST", "GET"])
def logout():
logout_user()
return redirect('/')
#Добавление лота для аукциона
#app.route('/aal', methods=["POST", "GET"])
def photo_form():
form = AuctionLotForm()
if form.validate_on_submit():
cur_time = dt.datetime.now().replace(microsecond=0)
dir_name = 'img_folder' + str(os.urandom(6).hex())
i = 1
for photo in request.files.getlist('photos'):
a_lot_photos.save(photo, name=dir_name + '/' + str(i)+'.')
i += 1
new_auction_lot = AuctionLotModel(
a_lot_title=form.a_lot_title.data,
description=form.description.data,
base_price=form.base_price.data,
auction_duration=dt.timedelta(minutes=form.auction_duration.data),
end_date=cur_time + dt.timedelta(minutes=form.auction_duration.data),
photo_dir=dir_name,
)
db.session.add(new_auction_lot)
db.session.commit()
return redirect('/')
return render_template('add_auction_lot.html', form=form)
#Просмотр профиля лота
#app.route('/lot/<lot_id>')
def lot_view(lot_id):
lot = AuctionLotModel.query.filter_by(id=lot_id).one_or_404()
return render_template('a_lot_view.html', lot=lot)
#Обработка 404
#app.errorhandler(404)
def error(error):
return render_template('404.html')
#app.before_request
def before_request():
g.user = current_user
#Media folder custom endpoint
#app.route('/media/<path:filename>')
def media(filename):
return send_from_directory('media', filename)
MODELS.PY
from flask_login import UserMixin
from datetime import datetime
from main_app import db, manager
current_date = datetime.now().replace(microsecond=0)
class User(db.Model, UserMixin):
__tablename__ = 'users_table'
id = db.Column(db.Integer, primary_key=True)
#Обязательные поля
real_name = db.Column(db.String(40), nullable=False)
date_of_birth = db.Column(db.Date, nullable=False)
username = db.Column(db.String(30), nullable=False, unique=True)
email = db.Column(db.String(255), nullable=False, unique=True)
password = db.Column(db.String(255), nullable=False)
#Автозаполняющиеся поля
joining_date = db.Column(db.Date, nullable=False, default=current_date)
email_is_verified = db.Column(db.Boolean, nullable=False, default=False)
def __init__(self, real_name, date_of_birth, username, email, password):
self.real_name = real_name
self.date_of_birth = date_of_birth
self.username = username
self.email = email
self.password = password
#manager.user_loader
def user_loader(user_id):
return User.query.filter_by(id=user_id).first()
class LotModel(db.Model):
__tablename__ = 'lots_table'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(), nullable=False)
description = db.Column(db.Text(), nullable=False)
price = db.Column(db.Integer(), nullable=False)
date = db.Column(db.String(), nullable=False, default=current_date)
def __init__(self, title, description, price):
self.title = title
self.description = description
self.price = price
class AuctionLotModel(db.Model):
__tablename__ = 'auction_lots_table'
id = db.Column(db.Integer, primary_key=True)
a_lot_title = db.Column(db.String(), nullable=False)
description = db.Column(db.Text(), nullable=False)
base_price = db.Column(db.Integer(), nullable=False)
auction_duration = db.Column(db.Interval(), nullable=False)
photo_dir = db.Column(db.String(), nullable=False)
end_date = db.Column(db.DateTime(), nullable=False)
is_active = db.Column(db.Boolean, nullable=False, default=True)
current_bid = db.Column(db.Integer(), nullable=False, default=0)
date = db.Column(db.Date(), nullable=False, default=current_date)
def __init__(self, a_lot_title, description, base_price, auction_duration, photo_dir, end_date):
self.a_lot_title = a_lot_title
self.description = description
self.base_price = base_price
self.auction_duration = auction_duration
self.photo_dir = photo_dir
self.end_date = end_date
Faced with such a situation, I can not understand what needs to be written so that I consider what I choose to use from the select.
Here are the working parts of the code:
Models.py
class Customer(db.Model):
__tablename__ = 'customer'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(255), nullable=False)
surname = db.Column(db.String(255), nullable=False)
debt = db.Column(db.NUMERIC, nullable=False)
last_account = db.Column(db.NUMERIC, nullable=False)
last_bill_of_the_month = db.Column(db.DATETIME, nullable=False)
rate = db.Column(db.NUMERIC, nullable=False)
condition_id = db.Column(db.Integer, db.ForeignKey('condition.id_condition'), nullable=False)
status_id = db.Column(db.Integer, db.ForeignKey('status.id_status'), nullable=False)
payment_method_id = db.Column(db.Integer, db.ForeignKey('payment_method.id_payment_method'), nullable=False)
payment_type_id = db.Column(db.Integer, db.ForeignKey('payment_type.id_payment_type'), nullable=False)
forms.py
class AddClient(FlaskForm):
name = StringField(validators=[InputRequired()], render_kw={"placeholder": ""})
surname = StringField(validators=[InputRequired()], render_kw={"placeholder": ""})
debt = StringField(validators=[InputRequired()], render_kw={"placeholder": ""})
last_account = StringField(validators=[InputRequired()], render_kw={"placeholder": ""})
last_bill_of_the_month = StringField(validators=[InputRequired()], render_kw={"placeholder": ""})
rate = StringField(validators=[InputRequired()], render_kw={"placeholder": ""})
# condition_id = SelectField(validators=[InputRequired()], coerce=int)
condition_id = SelectField('condition', choices=[])
status_id = SelectField('status', choices=[])
payment_method_id = SelectField('payment_method', choices=[])
payment_type_id = SelectField('payment_type', choices=[])
submit = SubmitField("add")
views.py
#app.route('/addclient', methods=['GET', 'POST'])
def addclient():
formClient = AddClient()
formClient.condition_id.choices = [(conditions.id_condition, conditions.list_condition) for conditions in
Condition.query.all()]
formClient.status_id.choices = [(statuses.id_status, statuses.list_status) for statuses in
Status.query.all()]
formClient.payment_method_id.choices = [(payment_methods.id_payment_method, payment_methods.list_payment_method) for
payment_methods in
Payment_method.query.all()]
formClient.payment_type_id.choices = [(payment_types.id_payment_type, payment_types.list_payment_type) for
payment_types in
Payment_type.query.all()]
if formClient.validate_on_submit():
new_client = Customer(name=formClient.name.data, surname=formClient.surname.data, debt=formClient.debt.data,
last_account=formClient.last_account.data, last_bill_of_the_month=formClient.last_bill_of_the_month.data, rate=formClient.rate.data)
db.session.add(new_client)
db.session.commit()
return redirect('/cust')
return render_template('addclient.html', formclient=formClient)
addclient.html
<form method="POST" action="">
{{formclient.hidden_tag()}}
{{formclient.name()}}
{{formclient.surname()}}
{{formclient.debt()}}
{{formclient.last_account()}}
{{formclient.last_bill_of_the_month()}}
{{formclient.rate()}}
{{formclient.condition_id()}}
{{formclient.status_id()}}
{{formclient.payment_method_id()}}
{{formclient.payment_type_id()}}
{{formclient.submit()}}
</form>
I can read and write text. And here is the data that I cannot select. How to do it correctly ?
this helped me:
condition_id = SelectField('condition', choices=[], coerce=int)
status_id = SelectField('status', choices=[], coerce=int)
payment_method_id = SelectField('payment_method', choices=[], coerce=int)
payment_type_id = SelectField('payment_type', choices=[], coerce=int)
When selected, it will just return the number that refers to it
guys, im very new using Flask and flask-sqlalchemy. I have two tables one is for store clients data, and the other one is to store quotation values. They have a relationship one to many, One client could have many quotations, but a quotation only belong to one client.
class Clientes(db.Model):
__tablename__ = "clientes"
id = db.Column(db.Integer, primary_key=True)
servicios = db.Column(db.String(120), nullable=False)
nombres = db.Column(db.String(80), nullable=False)
apellidos = db.Column(db.String(80), nullable=False)
correo = db.Column(db.String(120), nullable=False)
empresa = db.Column(db.String(120), nullable=False)
celular = db.Column(db.String(50), nullable=False)
mensaje = db.Column(db.String(500), nullable=False)
checkbox = db.Column(db.Boolean, nullable=False)
cotizaciones = db.relationship('Cotizacion', cascade='all, delete', backref='clientes_cotizan', lazy=True)
def __init__(self, servicios, nombres, apellidos, correo, empresa, celular, mensaje, checkbox):
self.servicios = servicios
self.nombres = nombres
self.apellidos = apellidos
self.correo = correo
self.empresa = empresa
self.celular = celular
self.mensaje = mensaje
self.checkbox = checkbox
def __repr__(self):
return '<Clientes %r>' % self.id
class Cotizacion(db.Model):
__tablename__ = "cotizacion"
id = db.Column(db.Integer, primary_key=True)
numero_personas = db.Column(db.Integer, nullable=False)
valor_personas = db.Column(db.Integer, nullable=False)
numero_horas = db.Column(db.Integer, nullable=False)
valor_hora = db.Column(db.Integer, nullable=False)
descuento = db.Column(db.Integer, nullable=False)
# LLAVE FORANEA
cliente_id = db.Column(db.Integer, db.ForeignKey("clientes.id"), nullable=False)
def __init__(self, numero_personas, valor_personas, numero_horas, valor_hora, descuento, cliente_id):
self.numero_personas = numero_personas
self.valor_personas = valor_personas
self.numero_horas = numero_horas
self.valor_hora = valor_hora
self.descuento = descuento
self.cliente_id = cliente_id
def __repr__(self):
return '<Cotizacion %r>' % self.id
This is my view
#app.route('/cotizaciones/crear/<int:id>', methods=("GET", "POST"))
#login_required
def crearcotizacion(id):
client = (db.session.query(Clientes).filter_by(id=id).one())
form = creacion_Cotizacion(request.form)
clientes_cotizan = db.session.query(Clientes, Cotizacion.id).join(Cotizacion).filter(Clientes.id).first()
cotizan = Cotizacion(
numero_personas=form.numero_personas.data,
valor_personas=form.valor_personas.data,
numero_horas=form.numero_horas.data,
valor_hora=form.valor_hora.data,
descuento=form.descuento.data,
cliente_id = clientes_cotizan
)
if current_user.role == True:
if request.method == 'POST':
try:
db.session.add(cotizan)
db.session.commit()
flash('La cotización ha sido creado exitosamente', 'success')
return render_template('crearcotizacion.html', client=client, form=form, id=id)
except InvalidRequestError:
db.session.rollback()
flash(f"Something went wrong!", "danger")
except IntegrityError:
db.session.rollback()
flash(f"La Cotizacion ya existe!.", "warning")
except DataError:
db.session.rollback()
flash(f"Entrada Inválida", "warning")
except InterfaceError:
db.session.rollback()
flash(f"Error al conectarse a la base de datos", "danger")
except DatabaseError:
db.session.rollback()
flash(f"Error de conexión con la base de datos", "danger")
except BuildError:
db.session.rollback()
flash(f"Un error ha ocurrido!", "danger")
else:
abort(401)
return render_template('crearcotizacion.html', nombres=current_user.nombres, correo=current_user.correo, role=current_user.role, id=id, client=client, form=form)
When i enter to /cotizaciones/crear/int:id and select one customer, the second page where i add the quotations value, when create quotation button is clicked an error is raised and i dont know how resolve this: Quotation already exists. Also, I dont know how foreign key is populated. Thanks for all your help.
When you create your Cotizacion object, you are trying to populate the foreignkey column, cliente_id. Instead, you should populate its backref of clientes_cotizan. It should be like this, where clientes_cotizan is populated by a client object you have queried with your selected id.
client = (db.session.query(Clientes).filter_by(id=id).one())
cotizan = Cotizacion(
numero_personas=form.numero_personas.data,
...,
clientes_cotizan = client
)
Note you will also need to edit your __init__ function to accept this clientes_cotizan instead of the cliente_id. It should be like this:
def __init__(self, numero_personas, ..., clientes_cotizan):
self.numero_personas = numero_personas
...
self.clientes_cotizan = clientes_cotizan
I am trying to build a webpage with a Project class and Project class will have multiple image files.
I can upload and store the image files but can't insert the file paths of images to database. So i can call the image paths from db. I have a sqlite db and i use Flask-SQLAlchemy.
Here is my Project Class. I've messed up a bit.
class Project(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(120), nullable=False)
date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
description = db.Column(db.Text, nullable=False)
header_image = db.Column(db.String(30), nullable=False, default='default_project.jpg')
project_images = db.relationship('ImageSet', backref='project', lazy=True, uselist=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
def __repr__(self):
return f"Project('{self.title}', {self.date_posted}')"
class ImageSet(db.Model):
id = db.Column(db.Integer, primary_key=True)
imageset = db.Column(db.String(120), nullable=False)
project_id = db.Column(db.Integer, db.ForeignKey('project.id'), nullable=False)
And this is the route and function to add projects
def save_picture(form_picture):
random_hex = secrets.token_hex(8)
_, f_ext = os.path.splitext(form_picture.filename)
picture_fn = random_hex + f_ext
picture_path = os.path.join(app.root_path, 'static/images/project_images', picture_fn)
output_size = (1280, 720)
i = Image.open(form_picture)
i.thumbnail(output_size)
i.save(picture_path)
return picture_fn
#app.route('/add_project', methods=["GET", "POST"])
#login_required
def add_project():
form = AddProjectForm()
imageset = ImageSet()
if form.validate_on_submit():
if form.header_image.data:
header_image = save_picture(form.header_image.data)
if form.project_images.data:
for image in form.project_images.data:
image = save_picture(image)
project = Project(title=form.title.data, description=form.description.data, project_images=, user_id=current_user.id)
db.session.add(project)
db.session.commit()
flash('Project Successfully Added', 'succes')
return render_template('add_project.html', title='Add Project', form=form)
return render_template('add_project.html', title='Add Project', form=form)
Thanks to #JosefKorbel, i've figured out the solution.
For anyone who may need the answer of the problem:
I used one-to-many relationship in classes.
class Project(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(120), nullable=False)
date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
description = db.Column(db.Text, nullable=False)
header_image = db.Column(db.String(30), nullable=False, default='default_project.jpg')
project_images = db.relationship('ImageSet', backref='project_images', lazy=True, uselist=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
def __repr__(self):
return f"Project('{self.title}', {self.date_posted}')"
class ImageSet(db.Model):
id = db.Column(db.Integer, primary_key=True)
image = db.Column(db.String(120), nullable=False)
project_id = db.Column(db.Integer, db.ForeignKey('project.id'), nullable=False)
Route, image saving functions:
def save_picture(form_picture):
random_hex = secrets.token_hex(8)
_, f_ext = os.path.splitext(form_picture.filename)
picture_fn = random_hex + f_ext
picture_path = os.path.join(app.root_path, 'static/images/project_images', picture_fn)
output_size = (1280, 720)
i = Image.open(form_picture)
i.thumbnail(output_size)
i.save(picture_path)
return picture_fn
#app.route('/add_project', methods=["GET", "POST"])
#login_required
def add_project():
form = AddProjectForm()
if form.validate_on_submit():
if form.header_image.data:
header_image = save_picture(form.header_image.data)
project = Project(title=form.title.data, description=form.description.data, header_image=header_image, user_id=current_user.id)
if form.project_images.data:
for image in form.project_images.data:
image = save_picture(image)
project.project_images.append(ImageSet(image=image))
time.sleep(2)
db.session.add(project)
db.session.commit()
flash('Project Successfully Added', 'succes')
return render_template('add_project.html', title='Add Project', form=form)
return render_template('add_project.html', title='Add Project', form=form)
i used time.sleep(2) before proccessing each image because sqlite is locking the database if i dont wait.
class Role(db.Model):
__tablename__ = 'roles'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True)
default = db.Column(db.Boolean, default=False, index=True)
permissions = db.Column(db.Integer)
users = db.relationship('User', backref='role', lazy='dynamic')
class User(UserMixin, db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.Integer, unique=True, index=True)
username = db.Column(db.String(64), unique=True, index=True)
role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
password_hash = db.Column(db.String(128))
confirmed = db.Column(db.Boolean, default=False)
def can(self, permissions):
print(self.role) #None
return self.role is not None and (self.role.permissions & permissions) == permissions
#main.route('/',methods=['GET', 'POST'])
def index():
form = PostForm()
print(current_user.role) #None
print(current_user.can(Permission.WRITE_ARTICLES)) #False
if current_user.can(Permission.WRITE_ARTICLES) and form.validate_on_submit():
post = Post(body=form.body.data, author=current_user._get_current_object())
db.session.add(post)
return redirect(url_for('.index'))
posts = Post.query.order_by(Post.timestamp.desc()).all()
return render_template('index.html', form=form, posts=posts)
sqlite> .tables
alembic_version posts roles users
sqlite> select * from roles;
1|Administrator|0|255
2|Moderator|0|15
3|User|1|7
there is data in roles, but print(current_user.role) is None,and When I call the can function in class User, print(self.role) is also None.
I can't understand why self.role is None?