2013-10-02 46 views
8

我使用factory_boy來創建測試裝置。我有兩個簡單的工廠,由SQLAlchemy模型(簡化如下)支持。避免與factory_boy工廠重複使用

我希望能夠多次呼叫AddressFactory.create(),並且如果它不存在則創建Country,否則我希望它重新使用現有記錄。

class CountryFactory(factory.Factory): 
    FACTORY_FOR = Country 

    cc = "US" 
    name = "United States" 


class AddressFactory(factory.Factory): 
    FACTORY_FOR = Address 

    name = "Joe User" 
    city = "Seven Mile Beach" 
    country = factory.SubFactory(CountryFactory, cc="KY", name="Cayman Islands") 

我的問題是:我怎麼可以設置這些工廠,使factory_boy不會嘗試創建一個新的國家或地區每創造出一個地址的時間?

+0

你看看[factory.alchemy](https://github.com/rbarrois/factory_boy/blob/master/factory /alchemy.py)? – javex

+0

不確定你在那個鏈接中指的是什麼;這個特定文件中沒有任何東西似乎有幫助。我已經查看了factory_boy和SQLAlchemy工廠的文檔,但我沒有看到有關重新使用記錄的任何信息。基本上尋找「查找或創建」類型的功能。 –

+0

經過對此的更多研究後,簡短的回答是你不能這樣做。支持[使用Django模型獲取或創建](https://factoryboy.readthedocs.org/en/latest/orms.html#factory.django.DjangoModelFactory.FACTORY_DJANGO_GET_OR_CREATE),但不支持SQLAlchemy。我將這個問題解決了,因爲我希望爲這些日子中的一個添加SQLAlchemy支持,如果沒有人能夠勝任我的話。 –

回答

4

在最新出廠的男孩== 2.3.1您可以添加FACTORY_DJANGO_GET_OR_CREATE

class CountryFactory(factory.django.DjangoModelFactory): 
    FACTORY_FOR = 'appname.Country' 
    FACTORY_DJANGO_GET_OR_CREATE = ('cc',) 

    cc = "US" 
    name = "United States" 

假設CC字段是唯一標識符。

+0

正如我在上面的問題和後續評論中提到的,我正在使用SQLAlchemy。我知道這存在於Django中,但這對我沒有幫助。我尋找的功能在工廠男孩中並不存在,我仍然沒有時間自己添加它。 –

2

雖然你說得對,有基於SQLAlchemy的,工廠沒有get_or_create功能,如果已經存在,你想作爲一個外鍵使用的對象,您可以遍歷它們:

http://factoryboy.readthedocs.org/en/latest/recipes.html#choosing-from-a-populated-table

所以可以想象,你可以通過使用一個懶惰屬性來檢測工廠中的解決方案,該屬性首先檢查數據庫中是否存在對象,如果是,則使用此方法遍歷它們,但如果該對象不存在,它會調用SubFactory先創建對象。

+0

這絕對是一個拙劣的解決方案,如果您提交了一個爲SQLAlchemy添加了get_or_create功能的PR,那就更好了;-) –

0

另一個拙劣的解決方案是覆蓋工廠的create方法,通過查詢和緩存結果來搜索對象。

這個簡單的例子確實在**kwargs沒有過濾,但:

class StaticFactory(SQLAlchemyModelFactory):       

    counter = 0              
    cache = []              
    model = None              

    @classmethod              
    def create(cls, **kwargs):          
     if not cls.cache:           
      cls.cache = your_session.query(cls.model).all()  
     instance = cls.cache[cls.counter]       
     cls.counter = (cls.counter + 1) % len(cls.cache)    
     return instance