Python sqlalchemy获取一个用户的所有评分

huangapple go评论127阅读模式
英文:

Python sqlalchemy get all ratings from one user

问题

我有一个问题。例如,我有两个表 - userssuggestions

每个用户可以对这个建议给出一些评分,例如,有一个建议 "改进界面"。

用户 #1 给了这个建议一个评分为 10,而用户 #2 给了它一个评分为 3。

接下来的建议 "修复错误",只被用户 #1 评分,他给了它一个评分为 5。

我想做的是以某种方式获取每个用户给予所有建议的评分。这是否可能?我该如何做?

这是基本的代码,我不知道我的下一步应该是什么。

  1. class Suggestion(Base):
  2. __tablename__ = "suggestions"
  3. s_id = Column("s_id", Integer, primary_key=True, autoincrement=True)
  4. content = Column("content", String, nullable=False)
  5. rating = Column("rating", Integer, nullable=False, default=0)
  6. def __repr__(self):
  7. return f"Suggestion #{self.id}: {self.content}"
  8. class User(Base):
  9. __tablename__ = "users"
  10. user_id = Column("user_id", Integer, primary_key=True)
  11. def __init__(self, user_id):
  12. self.user_id = user_id
  13. def __repr__(self):
  14. return f"User #{self.user_id}"
英文:

I have a question. For example, I have two tables - users and suggestions.

Each user can give some rating to this suggestion, for example, there is a suggestion "Improve the interface".

User #1 gives this suggestion a rating of 10, and user #2 gives it a rating of 3.

The next suggestion, "Fix bugs", was rated only by user #1, who gave it a rating of 5.

What I want to do is to somehow get every rating that a user has given to all the suggestions. Is it possible to do this? How could I do it?

Here is the basic code, and I don't know what my next steps should be.

  1. class Suggestion(Base):
  2. __tablename__ = "suggestions"
  3. s_id = Column("s_id", Integer, primary_key=True, autoincrement=True)
  4. content = Column("content", String, nullable=False)
  5. rating = Column("rating", Integer, nullable=False, default=0)
  6. def __repr__(self):
  7. return f"Suggestion #{self.id}: {self.content}"
  8. class User(Base):
  9. __tablename__ = "users"
  10. user_id = Column("user_id", Integer, primary_key=True)
  11. def __init__(self, user_id):
  12. self.user_id = user_id
  13. def __repr__(self):
  14. return f"User #{self.user_id}"

答案1

得分: 3

这是一个多对多的关系(一个用户可以对多个建议进行评分,一个建议可以被多个用户评分),因此你可以使用一个用户和建议之间的关联表来建模。

请查看以下文档了解更多信息:
关联对象

这是一个示例实现。我正在使用 dataclass 集成来自动生成 __init____repr__ 方法:

  1. from __future__ import annotations
  2. from sqlalchemy import ForeignKey, String, create_engine, select
  3. from sqlalchemy.orm import Mapped, MappedAsDataclass, sessionmaker
  4. from sqlalchemy.orm import mapped_column
  5. from sqlalchemy.orm import DeclarativeBase
  6. from sqlalchemy.orm import relationship
  7. class Base(MappedAsDataclass, DeclarativeBase):
  8. pass
  9. class User(Base):
  10. __tablename__ = "user"
  11. id: Mapped[int] = mapped_column(primary_key=True)
  12. ratings: Mapped[list[Rating]] = relationship(init=False, repr=False)
  13. class Rating(Base):
  14. __tablename__ = "rating"
  15. user_id: Mapped[int] = mapped_column(
  16. ForeignKey("user.id"),
  17. primary_key=True,
  18. )
  19. suggestion_id: Mapped[int] = mapped_column(
  20. ForeignKey("suggestion.id"),
  21. primary_key=True,
  22. )
  23. score: Mapped[int] = mapped_column(default=0)
  24. suggestion: Mapped[Suggestion] = relationship(init=False, repr=False)
  25. class Suggestion(Base):
  26. __tablename__ = "suggestion"
  27. id: Mapped[int] = mapped_column(primary_key=True, init=False)
  28. content: Mapped[str] = mapped_column(String(255), nullable=False)
  29. DATABASE_URL = "postgresql+psycopg2://test_username:test_password@localhost:5432/test"
  30. engine = create_engine(
  31. DATABASE_URL,
  32. )
  33. Session = sessionmaker(
  34. bind=engine,
  35. )
  36. if __name__ == "__main__":
  37. Base.metadata.create_all(engine)
  38. # create initial users and suggestions
  39. with Session.begin() as session:
  40. session.add_all([
  41. User(id=1),
  42. User(id=2),
  43. Suggestion(content="Improve the interface."),
  44. Suggestion(content="Fix bugs."),
  45. ])
  46. # users rating suggestions:
  47. with Session() as session:
  48. suggestion1_id = session.scalars(
  49. select(Suggestion.id).filter_by(content="Improve the interface.")
  50. ).one()
  51. suggestion2_id = session.scalars(
  52. select(Suggestion.id).filter_by(content="Fix bugs.")
  53. ).one()
  54. session.add_all([
  55. Rating(user_id=1, suggestion_id=suggestion1_id, score=10),
  56. Rating(user_id=2, suggestion_id=suggestion1_id, score=3),
  57. Rating(user_id=1, suggestion_id=suggestion2_id, score=5),
  58. ])
  59. session.commit()
  60. # getting ratings for a user:
  61. with Session() as session:
  62. user1 = session.get(User, 1)
  63. print(user1)
  64. for rating in user1.ratings:
  65. print(
  66. f" rated `{rating.suggestion.content}`"
  67. f" with a score of {rating.score}"
  68. )

这是输出结果:

  1. User(id=1)
  2. rated `Improve the interface.` with a score of 10
  3. rated `Fix bugs.` with a score of 5

这可以用多种方式完成,所以请阅读文档并选择你喜欢的方法。

英文:

This is a many-to-many relationship (a user can rate many suggestions, and a
suggestion can be rated by many users), so you can model this with an
association table between user and suggestion.

Please check the document on:
Association Object
for more information.

This is a sample implementation. I'm using the dataclass integration to
automatically generate the __init__ and __repr__ method:

  1. from __future__ import annotations
  2. from sqlalchemy import ForeignKey, String, create_engine, select
  3. from sqlalchemy.orm import Mapped, MappedAsDataclass, sessionmaker
  4. from sqlalchemy.orm import mapped_column
  5. from sqlalchemy.orm import DeclarativeBase
  6. from sqlalchemy.orm import relationship
  7. class Base(MappedAsDataclass, DeclarativeBase):
  8. pass
  9. class User(Base):
  10. __tablename__ = "user"
  11. id: Mapped[int] = mapped_column(primary_key=True)
  12. ratings: Mapped[list[Rating]] = relationship(init=False, repr=False)
  13. class Rating(Base):
  14. __tablename__ = "rating"
  15. user_id: Mapped[int] = mapped_column(
  16. ForeignKey("user.id"),
  17. primary_key=True,
  18. )
  19. suggestion_id: Mapped[int] = mapped_column(
  20. ForeignKey("suggestion.id"),
  21. primary_key=True,
  22. )
  23. score: Mapped[int] = mapped_column(default=0)
  24. suggestion: Mapped[Suggestion] = relationship(init=False, repr=False)
  25. class Suggestion(Base):
  26. __tablename__ = "suggestion"
  27. id: Mapped[int] = mapped_column(primary_key=True, init=False)
  28. content: Mapped[str] = mapped_column(String(255), nullable=False)
  29. DATABASE_URL = "postgresql+psycopg2://test_username:test_password@localhost:5432/test"
  30. engine = create_engine(
  31. DATABASE_URL,
  32. # echo=True,
  33. )
  34. Session = sessionmaker(
  35. bind=engine,
  36. )
  37. if __name__ == "__main__":
  38. Base.metadata.create_all(engine)
  39. # create initial users and suggestions
  40. with Session.begin() as session:
  41. session.add_all([
  42. User(id=1),
  43. User(id=2),
  44. Suggestion(content="Improve the interface."),
  45. Suggestion(content="Fix bugs."),
  46. ])
  47. # users rating suggestions:
  48. with Session() as session:
  49. suggestion1_id = session.scalars(
  50. select(Suggestion.id).filter_by(content="Improve the interface.")
  51. ).one()
  52. suggestion2_id = session.scalars(
  53. select(Suggestion.id).filter_by(content="Fix bugs.")
  54. ).one()
  55. session.add_all([
  56. Rating(user_id=1, suggestion_id=suggestion1_id, score=10),
  57. Rating(user_id=2, suggestion_id=suggestion1_id, score=3),
  58. Rating(user_id=1, suggestion_id=suggestion2_id, score=5),
  59. ])
  60. session.commit()
  61. # getting ratings for a user:
  62. with Session() as session:
  63. user1 = session.get(User, 1)
  64. print(user1)
  65. for rating in user1.ratings:
  66. print(
  67. f" rated `{rating.suggestion.content}`"
  68. f" with a score of {rating.score}"
  69. )

This is the output:

  1. User(id=1)
  2. rated `Improve the interface.` with a score of 10
  3. rated `Fix bugs.` with a score of 5

This can be done in numerous ways, so read the docs and pick one you like.

huangapple
  • 本文由 发表于 2023年7月17日 18:36:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/76703629.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定