You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Wagtail博客生成不同假日期?解决Faker重复日期问题

问题:使用Faker生成博客文章日期时所有文章日期相同

我正在测试博客文章是否按倒序排列,需要给每个创建的文章设置随机日期。用Faker库生成日期,但所有文章的假日期完全相同。这是Django auto_now的问题,还是我对Faker的用法有误?

Factory代码

fake = Faker()
mocked = fake.date_time()

class BlogPageFactory(wagtail_factories.PageFactory):
    class Meta:
        model = models.BlogPage

    with patch('django.utils.timezone.now', mocked):
        date = mocked
    # date = datetime.date.today()
    author = factory.SubFactory(UserFactory)
    slug = factory.sequence(lambda n: f"post{n}")
    snippet = factory.sequence(lambda n: f"Article {n} snippet...")
    body = "Test post..."
    featured_image = factory.SubFactory(wagtail_factories.ImageFactory)
    featured_article = False

Models代码

class BlogPage(Page):
    date = models.DateField("Post date")
    snippet = models.CharField(
        max_length=250, help_text="Excerpt used in article list preview card."
    )
    body = RichTextField(blank=True)
    tags = ClusterTaggableManager(through=BlogPageTag, blank=True)
    featured_image = models.ForeignKey("wagtailimages.Image", on_delete=models.CASCADE)
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT)
    featured_article = models.BooleanField(default=False)

    content_panels = Page.content_panels + [
        MultiFieldPanel(
            [
                FieldPanel("date"),
                FieldPanel("tags"),
            ],
            heading="Blog Information",
        ),
        FieldPanel("snippet"),
        FieldPanel("featured_image"),
        FieldPanel("body"),
        FieldPanel("author"),
        InlinePanel("page_comments", label="Comments"),
    ]

    search_fields = Page.search_fields + [index.SearchField("body")]

    parent_page_types = ["CategoryIndexPage"]
    subpage_types = []

    def serve(self, request, *args, **kwargs):
        """
        Method override to handle POST conditions for blog comments, ``BlogComment``.
        """
        from .forms import CommentForm

        if request.method == "POST":
            form = CommentForm(request.POST)
            if form.is_valid():
                new_comment = form.save(commit=False)
                new_comment.user = request.user
                new_comment.page = self
                new_comment.save()
                messages.success(
                    request,
                    "Your message was successfully "
                    "submitted and is awaiting moderation. "
                    "Thank you for contributing!",
                )
                return redirect(self.get_url())
        else:
            form = CommentForm

        return render(request, "blog/blog_page.html", {"page": self, "form": form})

解答

问题出在你对Faker和Factory Boy的用法上,和Django的auto_now无关——你的模型里date字段也没设置auto_now或auto_now_add。

原因分析

你在类定义外提前执行了fake.date_time(),把结果赋值给mocked,这个值是固定的时间对象。之后每次创建BlogPageFactory实例时,date字段都会用这个预先生成好的固定值,所以所有文章日期都一样。另外,你用patch的方式也不对,patch需要包裹的是会调用now()的代码,而不是直接赋值一个静态值。

解决方法

用Factory Boy的factory.LazyAttribute或者直接使用集成的factory.Faker,确保每次创建实例时都会生成新的随机日期:

修改后的Factory代码:

from factory import LazyAttribute

fake = Faker()

class BlogPageFactory(wagtail_factories.PageFactory):
    class Meta:
        model = models.BlogPage

    # 方式1:用LazyAttribute动态生成
    date = LazyAttribute(lambda _: fake.date_time().date())
    # 方式2:直接使用Factory Boy集成的Faker,更简洁
    # date = factory.Faker('date')
    
    author = factory.SubFactory(UserFactory)
    slug = factory.sequence(lambda n: f"post{n}")
    snippet = factory.sequence(lambda n: f"Article {n} snippet...")
    body = "Test post..."
    featured_image = factory.SubFactory(wagtail_factories.ImageFactory)
    featured_article = False

说明

  • LazyAttribute会在每次创建实例时执行传入的lambda函数,确保每次都生成新的随机时间并转成date类型匹配模型字段。
  • factory.Faker('date')是Factory Boy和Faker的集成用法,内部会自动处理每次生成新值的逻辑,代码更简洁。
  • 移除之前的patch代码,因为你不需要mocktimezone.now,直接给date字段赋值随机日期即可。

内容的提问来源于stack exchange,提问作者user3605767

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 08:23:22