I have editor
s and article
s. Many editors may be related to many articles and many articles may have many editors at same time.
My DB tables are
id | subject | text |
---|---|---|
1 | New Year Holidays | In this year... etc etc etc |
id | name | |
---|---|---|
1 | John Smith | some@email |
editor_id | article_id |
---|---|
1 | 1 |
My models are
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'))
)
My schemas are
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
My crud
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
My route
@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)
I want to post data for article creation API and automatically resolve and add editor relations, or raise error if some of editors doesn't exist:
{
"subject": "Fresh news"
"text": "Today is ..."
"editor_ids": [1, 2, ...]
}
HOW TO SET EDITORS HERE
place)?WHAT I NEED TO SET HERE
place)?WHAT I NEED TO SET HERE
place)?pydantic
and sqlalchemy
, any information will be welcomeYou add a tags class variable to the Post model. You use the db. relationship() method, passing it the name of the tags model ( Tag in this case). You pass the post_tag association table to the secondary parameter to establish a many-to-many relationship between posts and tags.
Many to Many relationship between two tables is achieved by adding an association table such that it has two foreign keys - one from each table's primary key.
orm_mode = True. It doesn't use : as for the type declarations before. This is setting a config value, not declaring a type. Pydantic's orm_mode will tell the Pydantic model to read the data even if it is not a dict , but an ORM model (or any other arbitrary object with attributes).
In Flask-SQLAlchemy, the backref parameter in relationship method allows you to declare a new property under a specified class as seen in the example in their docs: class Person(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50)) addresses = db.relationship('Address', backref='person ...
Not sure if my solution is most effective, but I did it by this way:
...
@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] = []
...
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
Any better ideas are welcome
A solution I found.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With