繁体   English   中英

fastapi + sqlalchemy + pydantic → 如何处理多对多关系

[英]fastapi + sqlalchemy + pydantic → how to process many-to-many relations

我有editorarticle 许多编辑可能与许多文章相关,许多文章可能同时有多个编辑。

我的数据库表是

  • 文章
ID 主题 文本
1个 新年假期 今年……等等等等
  • 编辑
ID 姓名 email
1个 约翰·史密斯 一些@电子邮件
  • 编辑文章关系
editor_id 文章编号
1个 1个

我的模特是

from sqlalchemy import Boolean, Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship

from database import Base

class Editor(Base):
    __tablename__ = "editor"

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String(32), unique=False, index=False, nullable=True)
    email = Column(String(115), unique=True, index=True)
    articles = relationship("Article",
                    secondary=EditorArticleRelation,
                    back_populates="articles",
                    cascade="all, delete")

class Article(Base):
    __tablename__ = "article"

    id = Column(Integer, primary_key=True, index=True)
    subject = Column(String(32), unique=True, index=False)
    text = Column(String(256), unique=True, index=True, nullable=True)
    editors = relationship("Editor",
                    secondary=EditorArticleRelation,
                    back_populates="editors",
                    cascade="all, delete")

EditorArticleRelation = Table('editorarticlerelation', Base.metadata,
    Column('editor_id', Integer, ForeignKey('editor.id')),
    Column('article_id', Integer, ForeignKey('article.id'))
)

我的模式是

from typing import Optional, List
from pydantic import BaseModel

class EditorBase(BaseModel):
    name: Optional[str]
    email: str

class EditorCreate(EditorBase):
    pass

class Editor(EditorBase):
    id: int

    class Config:
        orm_mode = True

class ArticleBase(BaseModel):
    subject: str
    text: str

class ArticleCreate(ArticleBase):
    # WHAT I NEED TO SET HERE???
    editor_ids: List[int] = []

class Article(ArticleBase):
    id: int
    editors: List[Editor] = []

    class Config:
        orm_mode = True

我的垃圾

def create_article(db: Session, article_data: schema.ArticleCreate):
    db_article = model.Article(subject=article_data.subject, text=article_data.text, ??? HOW TO SET EDITORS HERE ???)
    db.add(db_article)
    db.commit()
    db.refresh(db_article)
    return db_article

我的路线

@app.post("/articles/", response_model=schema.Article)
def create_article(article_data: schema.ArticleCreate, db: Session = Depends(get_db)):
    db_article = crud.get_article_by_name(db, name=article_data.name)
    if db_article:
        raise HTTPException(status_code=400, detail="article already registered")
    if len(getattr(article_data, 'editor_ids', [])) > 0:
        ??? WHAT I NEED TO SET HERE???
    return crud.create_article(db=db, article_data=article_data)

我想要什么 →

我想发布文章创建 API 的数据并自动解析和添加编辑器关系,或者如果某些编辑器不存在则引发错误:

{
  "subject": "Fresh news"
  "text": "Today is ..."
  "editor_ids": [1, 2, ...]
}

问题是:

  1. 如何正确设置 CRUD 操作( HOW TO SET EDITORS HERE地方)?
  2. 如何正确设置创建/读取模式和关系字段(尤其是WHAT I NEED TO SET HERE的位置)?
  3. 如何正确设置路由代码(尤其是WHAT I NEED TO SET HERE place)?
  4. 如果这里不可能自动解决关系,那么什么地方会更好地解决关系(检查编辑器是否存在等)? 路线还是路况?
  5. 也许我的方式根本不好? 如果您知道如何处理与pydanticsqlalchemy的多对多关系的任何示例,欢迎提供任何信息

我找到的解决方案。

def create_user_groups(db: Session, user_groups: schemas.UserGroupsBase):
    db_user = db.query(models.User).filter(models.User.id == user_groups.id_user).first()
    db_group = db.query(models.Group).filter(models.Group.id == user_groups.id_group).first()

    if not db_user and db_group:
        raise HTTPException(status_code=409, detail="User or Group not found in system.")

    db_user.groups.append(db_group)

    db.add(db_user)
    db.commit()
    db.refresh(db_user)
    return db_user

不确定我的解决方案是否最有效,但我是这样做的:

  • 路线(与问题相同):
...
@app.post("/articles/", response_model=schema.Article)
def create_article(article_data: schema.ArticleCreate, db: Session = Depends(get_db)):
    db_article = crud.get_article_by_name(db, name=article_data.name)
    if db_article:
        raise HTTPException(status_code=400, detail="article already registered")
    return crud.create_article(db=db, article_data=article_data)
...
  • 架构(与问题相同):
...
class ArticleCreate(ArticleBase):
    editor_ids: List[int] = []
...
  • crud(解决方案在这里):
def create_article(db: Session, article_data: schema.ArticleCreate):
    db_article = model.Article(subject=article_data.subject, text=article_data.text)
    if (editors := db.query(model.Editor).filter(model.Editor.id.in_(article_data.editor_ids))).count() == len(endpoint_data.topic_ids):
        db_article.topics.extend(editors)
    else:
        # even if at least one editor is not found, an error is raised
        # if existence is not matter you can skip this check and add relations only for existing data
        raise HTTPException(status_code=404, detail="editor not found")
    db.add(db_article)
    db.commit()
    db.refresh(db_article)
    return db_article

欢迎任何更好的想法

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM