В документации Django перечислены только примеры для переопределения save()
и delete()
. Однако я хотел бы определить дополнительную обработку для моих моделей только тогда, когда они созданы . Для любого, кто знаком с Rails, это будет эквивалентно созданию :before_create
фильтра. Это возможно?
django
django-models
django-forms
земля5харк
источник
источник
create
? Это интересное решение, но оно не сработает в тех случаях, когда объект создается с использованиемObject(**kwargs).save()
или любых других его вариаций.super(MyModel, self).save(*args, **kwargs)
?self.pk
- не лучший вариант, чтобы проверить, создается ли объект заново или просто обновляется. Иногда вы указываете идентификатор объекта во время создания (настраиваемое значение, не созданное базой данных, напримерKSUID
), и это приведет к тому, что это предложение никогда не будет выполняться ... Естьself._state.adding
значение, чтобы убедиться, сохраняется ли он в первый раз или просто обновляется, что помогает в тех случаях.пример того, как создать сигнал post_save (из http://djangosnippets.org/snippets/500/ )
from django.db.models.signals import post_save from django.dispatch import receiver @receiver(post_save, sender=User) def create_profile(sender, instance, created, **kwargs): """Create a matching profile whenever a user object is created.""" if created: profile, new = UserProfile.objects.get_or_create(user=instance)
вот вдумчивое обсуждение того, что лучше использовать: сигналы или пользовательские методы сохранения https://web.archive.org/web/20120815022107/http://www.martin-geber.com/ Thinkt/2007/10/29/ django-сигналы-vs-пользовательский-метод сохранения /
На мой взгляд, использование сигналов для этой задачи является более надежным, легким для чтения, но более длинным.
источник
instance.save()
. Таким образом, в этом случае также наблюдается снижение производительности, так как будет один запрос INSERT и один запрос UPDATE к базе данных.Это старый, есть принятый ответ, который работает (Зак), а также более идиоматический (Майкл Билстра), но поскольку это все еще первый результат в Google, который видит большинство людей, я думаю, нам нужно больше передовых методов современного django ответ в стиле здесь :
from django.db.models.signals import post_save class MyModel(models.Model): # ... @classmethod def post_create(cls, sender, instance, created, *args, **kwargs): if not created: return # ...what needs to happen on create post_save.connect(MyModel.post_create, sender=MyModel)
Дело вот в чем:
@classmethod
вместо,@staticmethod
потому что, скорее всего, вам понадобится ссылаться на статические члены класса в кодеЕще чище было бы, если бы ядро Django имело реальный
post_create
сигнал. (Imho, если вам нужно передать логический аргумент, чтобы изменить поведение метода, это должно быть 2 метода.)источник
Чтобы ответить на вопрос буквально,
create
метод в менеджере модели - это стандартный способ создания новых объектов в Django. Чтобы переопределить, сделайте что-нибудь вродеfrom django.db import models class MyModelManager(models.Manager): def create(self, **obj_data): # Do some extra stuff here on the submitted data before saving... # For example... obj_data['my_field'] = my_computed_value(obj_data['my_other_field']) # Now call the super method which does the actual creation return super().create(**obj_data) # Python 3 syntax!! class MyModel(models.model): # An example model my_field = models.CharField(max_length=250) my_other_field = models.CharField(max_length=250) objects = MyModelManager()
В этом примере я переопределяю метод
create
метода Manager, чтобы выполнить некоторую дополнительную обработку перед фактическим созданием экземпляра.ПРИМЕЧАНИЕ: код вроде
my_new_instance = MyModel.objects.create(my_field='my_field value')
выполнит этот модифицированный
create
метод, но код вродеmy_new_unsaved_instance = MyModel(my_field='my_field value')
не буду.
источник
Переопределение
__init__()
позволит вам выполнить код при создании экземпляра модели. Не забудьте позвонить родителям__init__()
.источник
Вы можете переопределить метод create с помощью настраиваемого менеджера или добавить метод класса в класс модели. https://docs.djangoproject.com/en/1.11/ref/models/instances/#creating-objects
источник
Предпочтительный ответ правильный, но тест, определяющий, создается ли объект, не работает, если ваша модель является производной от UUIDModel. Поле pk уже будет иметь значение.
В этом случае вы можете сделать это:
already_created = MyModel.objects.filter(pk=self.pk).exists()
источник