Django-заметки

Произошел врыв в Django в 2021, начинают появляться заметочки, рецептики, хочется иметь их все в одном месте


Тестирование

Тестирование дат

В респонсе дата приходит в виде строки, в drf-формате, типа такой:

2022-02-08T13:35:47.680868+03:00

Для приведения даты к drf-строке используй:

DateTimeField().to_representation(date)

Пример:

class Item(Model):
  created = DateTimeField()
  
class ItemSerializer(ModelSerializer):
  class Meta:
    model = Item
    fields = ('created', )

item = Item(created=dt.datetime.now())

data = ItemSerializer(item).data

self.assertEqual(
  data, 
  {'created': DateTimeField().to_representation(item.created),
} 

Аналогично для типов, которые при сериализации переводятся в особую строку, стоит использовать метод to_representation.

Напр. для Decimal: DecimalField(max_digits=..., decimal_places=...).to_representation(decimal_)

Генерация тестовых данных

Используем factory-boy

Генерация тестовых данных в виде словарей

Для простых объектов тоже используем factory-boy:

factory.build(dict, FACTORY_CLASS=UserFactory)

Для непростых объектов (с вложенными сущностями) - проследуйте на стек

Еще о датах

Допустим, есть сущность с полем - created - датой создания объекта, которая проставляется автоматически при первом сохранении в бд:

class Note(models.Model):
  text = models.CharField(...)
  created = models.DateTimeField(auto_now_add=True)

И мы хотим генерировать тестовые сущности, но с определенной датой:

class NoteFactory(factory.django.DjangoModelFactory):
  class Meta:
    model = Note
    
    
test_note = NoteFactory(created=dt.datetime(2022, 2, 14))

У test_note поле created будет равняться не dt.datetime(2022, 2, 14), а текущей, потому что auto_now_add=True

Чтобы была возможность указывать произвольное значение поля created, нужно использовать default=timezone.now:

created = models.DateTimeField(default=timezone.now)

Тогда, если не указывать created, то оно заполнится текущей датой, а если указывать, то оно будет таким, каким хотим:

test_note = NoteFactory(created=dt.datetime(2022, 2, 14))

assert test_note.created == dt.datetime(2022, 2, 14)