返回每个博客帖子的假日期-现在绕过django的auto

5us2dqdw  于 2023-05-01  发布在  Go
关注(0)|答案(2)|浏览(143)

我正在测试我的博客文章是否按时间顺序排列。要做到这一点,我必须为每个创建的帖子设置随机日期。我使用faker来设置日期。我得到了一个假的日期,但它是相同的日期为每一个职位。自动现在仍然是这里的问题,还是我没有正确使用Faker?
工厂:

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

型号:

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})
fhity93d

fhity93d1#

您当前的代码存在两个问题,导致您遇到的问题:
1.你在模块导入时生成一个 fixedmocked日期;
1.您实际上并没有用patch(..., mocked)覆盖任何auto_now

获取真正随机的mocked日期

问题来自于你的代码编写方式;在模块导入时计算mocked日期-因此对于所有将来的调用总是相同的。
为了获得一个动态值,你需要使用factory_boy的一个专用声明--每次要求工厂生成一个示例时,都会对它们进行评估。
我建议看看我的另一个答案,以获得更深入的解释。

覆盖模型中的date

在这里,你的model字段声明是一个“标准”Django字段,没有魔法;不需要修补django.utils.timezone.now(),因为将date=mocked传递到BlogPage.objects.create(...)将工作。* 顺便说一下,这正是factory_boy在引擎盖下执行的调用。*
如果你有一个带有auto_now_add的模型,Django不允许覆盖这个值--就像在他们的文档中看到的那样。
这将给您留下两个可能的选择:
1.将auto_now_add=True替换为default=timezone.now:当default是一个可调用对象时,Django将为模型的每个新示例执行可调用对象,除非调用者提供了一个值-就像你对工厂所做的那样;
1.如果这不可能,你可以重写_create()方法:

class BlogPageFactory(factory.django.DjangoModelFactory):
  ...

  date = factory.Faker("date_time")

  @classmethod
  def _create(cls, model_class, *args, **kwargs):
    # Extract the "date" kwarg, as an explicit value will be ignore
    # by auto_now_add
    date = kwargs.pop("date")

    # Force `timezone.now()` to always return the expected date
    # for the duration of the instance creation
    with patch("django.utils.timezone.now", lambda: date):

      # Let factory_boy actually create the instance
      return super()._create(model_class, *args, **kwargs)
zz2j4svz

zz2j4svz2#

尝试date_time_this_decade()

fake = Faker()

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

    date = fake.date_time_this_decade()
    ...

相关问题