2012-04-23 17 views
10

Obecnie używam factory_boy do tworzenia urządzeń w moich testach. Factory_boy Dokumenty wspomniane tylko o numerze SubFactory, które mogą działać w polu jako pole ForeignKey. Jednak nie było nic w stowarzyszeniu ManyToMany. Gdybym miał następujący model Post, w jaki sposób mógłbym stworzyć fabrykę?Python factory_boy biblioteka m2m w modelu Django?

class Post(models.Model): 
    title = models.CharField(max_length=100) 
    tags = models.ManyToManyField('tags.Tag') 

class PostFactory(factory.Factory): 
    FACTORY_FOR = Post 

    title = 'My title' 
    tags = ??? 
+0

Hey @Ngo dostałeś odpowiedź, która zadziałała? – Daryl

+0

@Daryl: nadpisywanie _prepare wydaje się być najłatwiejszym rozwiązaniem :) –

Odpowiedz

2

nie testowałem, ale jaki jest problem z:

class PostFactory(factory.Factory): 
    FACTORY_FOR = Post 
    title = 'My title' 

class TagFactory(factory.Factory): 
    FACTORY_FOR = Tag 

post = PostFactory() 
tag = TagFactory() 
post.tags.add(tag) 
+1

Tak, to działa. Ale chciałbym to zrobić: post = PostFactory() i nie będzie powiedzmy, że 4 tagi dodane automatycznie bez konieczności ręcznego określania post.tags.add (tag) –

+0

Nie sądzę, że factory_boy na to pozwala. Ale dlaczego po prostu nie stworzysz funkcji, która to zrobi dla ciebie? def PostFactoryWithFourTags(): post = PostFactory() dla _ w xrange (4): post.tags.add (TagFactory() return post – Ale

7

Można zastąpić _prepare classmethod:

class PostFactory(Factory): 
    FACTORY_FOR = Post 

    title = 'My title' 

    @classmethod 
    def _prepare(cls, create, **kwargs): 
     post = super(PostFactory, cls)._prepare(create, **kwargs) 
     if post.id: 
      post.tags = Tag.objects.all() 
     return post 

pamiętać, że nie można dodać znaczniki post, jeśli post nie ma identyfikatora.

11

Co sądzić o używaniu nowszej wersji factory_boy?

import random 
import factory 

class PostFactory(factory.Factory): 
    FACTORY_FOR = Post 
    title = factory.Sequence(lambda n: "This is test title number" + n) 
    @factory.post_generation(extract_prefix='tags') 
    def add_tags(self, create, extracted, **kwargs): 
     # allow something like PostFactory(tags = Tag.objects.filter()) 
     if extracted and type(extracted) == type(Tag.objects.all()): 
      self.tags = extracted 
      self.save() 
     else: 
      if Tag.objects.all().count() < 5: 
       TagFactory.create_batch(5, **kwargs) 
      for tag in Tag.objects.all().order_by('?')[:random.randint(1, 5)]: 
       self.tags.add(tag) 

pamiętać, że można użyć PostFactory(tags__field = 'some fancy default text'), ale polecam stworzyć dobrą TagFactory z sekwencjami ...

Powinieneś być w stanie związać PostFactory(tags = Tag.objects.filter()) ale ta część nie jest testowany ...