簡體   English   中英

factory_boy 中的一對多關系

[英]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")

現在我正在嘗試創建一個工廠,該工廠創建具有幾個地址的人員。 SubFactorySubFactory 但我只看到你如何在一對一的關系中使用它。 我知道我可以使用單獨的工廠創建地址然后附加它們,但我想做類似person = PersonFactory.create(num_addresses=4)` 的事情。

有誰知道這在 factory_boy 中目前是否可行?

我使用 factory_boy 2.4.1。

我在我的項目中使用這種模式。 假設您已經擁有AddressFactory

https://factoryboy.readthedocs.io/en/latest/reference.html?highlight=post_generation#factory.post_generation

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

基本上,只是聲明了幾個RelatedFactoryPersonFactory

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM