auto_add с FactoryBoy

Эта проблема: https://github.com/FactoryBoy/factory_boy/issues/102 описывает, как вы должны протестировать «созданное» поле в django.

Как это должно быть реализовано для auto_add (а не для auto_add_now)? У меня есть "обновленное" поле, но использую ли я

models.DateTimeField(auto_now=True) 

или переопределить метод .save() модели django

def save(self, *args, **kwargs):
    """On save, update updated timestamp"""
    self.updated = timezone.now
    return super(Task, self).save(*args, **kwargs)

Кажется, я не могу заставить FactoryBoy возвращать значение update, которое я хочу - он всегда возвращает timezone.now()

LazyAttribute(lambda o: o.created + timedelta(hours=1))   # ignored by auto_add

или используя метод _create(), как предложено в проблеме GitHub:

@classmethod
def _create(cls, target_class, *args, **kwargs)
    updated = kwargs.pop('updated', None)
    obj = super(TaskFactory, cls)._create(target_class, *args, **kwargs)
    if updated is not None:
        obj.updated = updated
        obj.save()   # <-- calls .save() method overriding with timezone.now()
    return obj

Как лучше всего добраться сюда?


person Liz    schedule 11.10.2018    source источник


Ответы (2)


Для тех, кто еще борется с этим, пока единственный способ, который я нашел, — это обезвреживать метод .save() в исходной модели, прежде чем переходить к Factory boy:

модели.ру:

updated = models.DateTimeField(default=timezone.now)
def save(self, *args, **kwargs):
    """On save, update updated timestamp"""
    self.updated = timezone.now
    return super(Task, self).save(*args, **kwargs)

фабрики.py:

updated = LazyAttribute(lambda o: o.created + timedelta(hours=1))

def patched_save(self, *args, **kwargs):
    return super(Task, self).save(*args, **kwargs)

Task.save = patched_save

но хотелось бы услышать альтернативные (вероятно, лучшие) предложения!

person Liz    schedule 11.10.2018

Просто добавьте что-то вроде этого в фабрику задач:

from django.db import models

@classmethod
def _create(cls, target_class, *args, **kwargs):
    updated = kwargs.pop('updated', None)
    task = super()._create(target_class, *args, **kwargs)

    if updated is not None:
        task.updated = updated
        models.Model.save(task)  # This does the magic

    return task

Примечание: мы называем models.Model.save(task), а не task.save()

person serghei    schedule 18.04.2021