2012-04-23 13 views
10

Tôi hiện đang sử dụng factory_boy để tạo đồ đạc trong các thử nghiệm của mình. Factory_boy tài liệu chỉ được đề cập về SubFactory có thể hoạt động giống như trường ForeignKey trong mô hình. Tuy nhiên, không có gì liên quan đến ManyToMany. Nếu tôi có một mô hình Post sau đây, làm thế nào tôi sẽ đi về việc tạo ra một nhà máy cho nó?Python factory_boy library m2m trong mô hình 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 bạn đã nhận được câu trả lời hoạt động chưa? – Daryl

+0

@Daryl: ghi đè _prepare có vẻ là giải pháp dễ dàng nhất :) –

Trả lời

2

tôi không kiểm tra nó, nhưng vấn đề là những gì với:

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

Vâng, hoạt động. Nhưng tôi muốn làm điều này: post = PostFactory() và sẽ có 4 tag được thêm tự động mà không cần phải tự định rõ post.tags.add (tag) –

+0

Tôi không nghĩ factory_boy cho phép điều đó. Nhưng tại sao bạn không chỉ tạo ra một chức năng mà làm điều đó cho bạn? def PostFactoryWithFourTags(): post = PostFactory() cho _ in xrange (4): post.tags.add (TagFactory() bài trả lại – Ale

7

Bạn có thể ghi đè lên _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 

Lưu ý rằng bạn không thể thêm thẻ vào một bài đăng nếu bài đăng không có ID.

11

Điều gì về post_generation hook - Tôi giả sử Bạn sử dụng phiên bản mới hơn của 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) 

Lưu ý rằng bạn có thể sử dụng PostFactory(tags__field = 'some fancy default text'), nhưng tôi khuyên bạn nên tạo tốt TagFactory với Sequences ...

Bạn sẽ có thể để ràng buộc PostFactory(tags = Tag.objects.filter()) nhưng phần này không được kiểm tra ...