[英]One-to-many relationships in factory_boy
我使用 SQLalchemy 作為我的 ORM,並試圖將我的測試裝置移植到 factory_boy。 我的模式包括一對多關系中的兩個對象。 即一個模型的實例具有類似結構的列表,其中包含另一個模型的實例。 例子:
class Person(...):
id = Column(Integer, primary_key=True)
name = Column(Text)
[...]
class Address(...):
id = Column(Integer, primary_key=True)
city = Column(Text)
[...]
person_id = Column(Integer, ForeignKey('person.id'))
person = relationship("Person", backref="addresses")
現在我正在嘗試創建一個工廠,該工廠創建具有幾個地址的人員。 SubFactory
有SubFactory
。 但我只看到你如何在一對一的關系中使用它。 我知道我可以使用單獨的工廠創建地址然后附加它們,但我想做類似person =
PersonFactory.create(num_addresses=4)` 的事情。
有誰知道這在 factory_boy 中目前是否可行?
我使用 factory_boy 2.4.1。
我在我的項目中使用這種模式。 假設您已經擁有AddressFactory
。
class PersonFactory(factory.alchemy.SQLAlchemyFactory):
class Meta:
model = Person
@factory.post_generation
def addresses(obj, create, extracted, **kwargs):
if not create:
return
if extracted:
assert isinstance(extracted, int)
AddressFactory.create_batch(size=extracted, person_id=self.id, **kwargs)
用法
PersonFactory(addresses=4)
這將創建具有 4 個Address
Person
這也可以接受 kwargs
PersonFactory(addresses=2, addresses__city='London')
這將創建具有 2 個Address
Person
,其city
字段設置為'London'
這是可能有幫助的博客文章https://simpleit.rocks/python/django/setting-up-a-factory-for-one-to-many-relationships-in-factoryboy/
我有這個確切的問題,並對這里缺乏好的答案感到失望。 事實證明這是可能的! 把這個留在這里給那些有同樣問題的人。
首先,您的模型需要從 ForeignKey 定義相反模型上的關系,因此它應該如下所示:
class Person(...):
id = Column(Integer, primary_key=True)
name = Column(Text)
addresses = relationship("Person", backref="person")
[...]
class Address(...): id = Column(Integer, primary_key=True) city = Column(Text) [...] person_id = Column(Integer, ForeignKey('person.id'))
然后,在您的 PersonFactory 上,您可以添加一個 post_generation 鈎子,如下所示:
class PersonFactory(BaseFactory):
[...attributes...]
@factory.post_generation
def addresses(self, create, extracted, **kwargs):
return AddressFactory.create_batch(4)
並用您想要的任何數字替換“4”。
顯然,您還需要定義 AddressFactory。
目前,沒有辦法實現“多對一的相關RelatedFactory
”,使其“融入您的工廠”......
也就是說,在實例化您的PersonFactory
時,可以通過一些PersonFactory
來實現此行為。
以下食譜將為您提供所需的東西:
from sqlalchemy import create_engine, Integer, Text, ForeignKey, Column
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, scoped_session, sessionmaker
import factory
from factory.alchemy import SQLAlchemyModelFactory as sqla_factory
import random
engine = create_engine("sqlite:////tmp/factory_boy.sql")
session = scoped_session(sessionmaker(bind=engine))
Base = declarative_base()
class Person(Base):
id = Column(Integer, primary_key=True)
name = Column(Text)
addresses = relationship("Address", backref="person")
class Address(Base):
id = Column(Integer, primary_key=True)
street = Column(Text)
street_number = Column(Integer)
person_id = Column(Integer, ForeignKey('person.id'))
class AddressFactory(sqla_factory):
class Meta:
model = Address
sqlalchemy_session = session
street_number = random.randint(0, 10000)
street = "Commonwealth Ave"
class PersonFactory(sqla_factory):
class Meta:
model = Person
sqlalchemy_session = session
name = "John Doe"
Base.metadata.create_all(engine)
for i in range(100):
person = PersonFactory(addresses=AddressFactory.create_batch(3))
@Kristen 指出了正確的方向,但 AdderssFactory 與 Person 無關。 在Django 中,我們可以像這樣使用post_generation裝飾器。
class PersonFactory(BaseFactory):
@factory.post_generation
def addresses(self, create, extracted, **kwargs):
self.addresses_set.add(AddressFactory(person=self))
您可以使用此處描述的解決方案: http : //factoryboy.readthedocs.org/en/latest/recipes.html#reverse-dependencies-reverse-foreignkey
基本上,只是聲明了幾個RelatedFactory
您PersonFactory
:
class PersonFactory(factory.alchemy.SQLAlchemyFactory):
class Meta:
model = Person
address_1 = factory.RelatedFactory(AddressFactory, 'person')
address_2 = factory.RelatedFactory(AddressFactory, 'person')
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.