1
resposta

[Dúvida] Definir relacionamentos de forma correta

Boa tarde!

Estou desenvolvendo um projeto em Flask, usando o flask-sqlalchemy e sqlite, onde:

Estou realizando a definição de 3 tabelas que devem ter certos relacionamentos, mas não consegui fazer a definição completa das mesmas... Os relacionamentos são os seguintes:

Uma empresa pode ter vários usuários e varios estudos. Para cada estudo, podem estar relacionados diversos usuarios. Usuarios podem ser relacionados diversos estudos Usuarios de diferentes empresas não podem ser relacionados no mesmo estudo.

Outros pontos: Não podem existir usuarios sem empresas. Não podem existir estudos sem ao menos um usuário relacionado.

Dado esse conjunto de requisitos, consegui chegar no seguinte codigo:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy


app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///app.db"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)



from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy import Uuid, Float, String, ForeignKey, Integer

import uuid


class StudyUser(db.Model):
    __tablename__ = 'study_user'
    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    user_id: Mapped[Uuid] = mapped_column(Uuid, ForeignKey('user.id')) #
    study_id: Mapped[Uuid] = mapped_column(Uuid, ForeignKey('study.id')) #



class Company(db.Model):
    __tablename__ = 'company'
    id: Mapped[Uuid] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4())
    name: Mapped[str] = mapped_column(String(32))
    users = relationship('User', backref = 'empresa')
    studies = relationship('Study', backref='empresa')



class User(db.Model):
    __tablename__ = 'user'
    id: Mapped[Uuid] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4())
    name: Mapped[str] = mapped_column(String(32))
    empresa_id: Mapped[Uuid] = mapped_column(Uuid, ForeignKey('company.id'))
    studies = relationship('Study', secondary = StudyUser.__table__, backref = 'usuario')



class Study(db.Model):
    __tablename__ = 'study'
    id: Mapped[Uuid] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4())
    name: Mapped[str] = mapped_column(String(32))
    company_id = mapped_column(Uuid, ForeignKey('company.id'))

O problema que encontrei é que ainda é possivel cadastrar usuários de diferentes empresas no mesmo estudo, e também é possível criar estudos associados à uma empresa, e ter somente usuários de outra empresa associados ao mesmo. Alguém possui uma indicação de como (ou mesmo se é possível) corrigir essa falha corrigindo a estrutura das tabelas?

1 resposta

Parece que você está enfrentando problemas na definição dos relacionamentos entre as tabelas no seu projeto Flask com Flask-SQLAlchemy e SQLite. Com base nos requisitos mencionados, é possível fazer algumas alterações na estrutura das tabelas para atender às restrições desejadas.

Aqui está uma sugestão de como você pode modificar as definições das tabelas para atender aos requisitos:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint
from sqlalchemy.orm import relationship

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///app.db"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)


class Company(db.Model):
    __tablename__ = 'company'
    id = Column(Integer, primary_key=True)
    name = Column(String(32), unique=True)
    users = relationship('User', backref='company')
    studies = relationship('Study', backref='company')


class User(db.Model):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True)
    name = Column(String(32))
    company_id = Column(Integer, ForeignKey('company.id'), nullable=False)
    studies = relationship('Study', secondary='study_user', backref='users')

    __table_args__ = (
        UniqueConstraint('id', 'company_id'),
    )


class Study(db.Model):
    __tablename__ = 'study'
    id = Column(Integer, primary_key=True)
    name = Column(String(32))
    company_id = Column(Integer, ForeignKey('company.id'), nullable=False)


class StudyUser(db.Model):
    __tablename__ = 'study_user'
    id = Column(Integer, primary_key=True)
    user_id = Column(Integer, ForeignKey('user.id'), nullable=False)
    study_id = Column(Integer, ForeignKey('study.id'), nullable=False)

    __table_args__ = (
        UniqueConstraint('user_id', 'study_id'),
    )

Aqui estão as principais alterações feitas:

Na tabela User, adicionei uma restrição única (UniqueConstraint) para garantir que um usuário não possa estar associado a mais de uma empresa.

Na tabela StudyUser, adicionei uma restrição única para garantir que um usuário não possa estar associado ao mesmo estudo mais de uma vez.

Essas restrições únicas ajudarão a garantir que os relacionamentos entre usuários, empresas e estudos atendam aos requisitos específicos mencionados.

Lembre-se de aplicar as alterações nas definições das tabelas e atualizar o banco de dados. Você pode fazer isso executando os seguintes comandos no seu projeto Flask:

flask db migrate
flask db upgrade

Esses comandos irão criar as tabelas e aplicar as alterações no banco de dados de acordo com as definições atualizadas.

Espero que isso ajude! Se você tiver mais dúvidas, por favor, deixe-me saber.