Заполнение поля django с помощью pre_save()?
class TodoList(models.Model):
title = models.CharField(maxlength=100)
slug = models.SlugField(maxlength=100)
def save(self):
self.slug = title
super(TodoList, self).save()
Я предполагаю, что выше описано, как создавать и хранить пули, когда заголовок вставляется в таблицу TodoList, если нет, пожалуйста, исправьте меня!
Во всяком случае, я изучал pre_save() как еще один способ сделать это, но не могу понять, как это работает. Как вы это делаете с помощью pre_save()?
это как
def pre_save(self):
self.slug = title
Я предполагаю, что нет. Что такое код для этого?
Спасибо!
Ответы
Ответ 1
Скорее всего, вы обращаетесь к сигналу django pre_save
. Вы можете настроить что-то вроде этого:
from django.db.models.signals import pre_save
from django.dispatch import receiver
from django.template.defaultfilters import slugify
@receiver(pre_save)
def my_callback(sender, instance, *args, **kwargs):
instance.slug = slugify(instance.title)
Если вы не включаете аргумент отправителя в декоратор, например @receiver(pre_save, sender=MyModel)
, вызов будет вызываться для всех моделей.
Вы можете поместить код в любой файл, который анализируется во время выполнения вашего приложения, models.py
- хорошее место для этого.
Ответ 2
@receiver(pre_save, sender=TodoList)
def my_callback(sender, instance, *args, **kwargs):
instance.slug = slugify(instance.title)
Ответ 3
вы можете использовать django signals.pre_save:
from django.db.models.signals import post_save, post_delete, pre_save
class TodoList(models.Model):
@staticmethod
def pre_save(sender, instance, **kwargs):
#do anything you want
pre_save.connect(TodoList.pre_save, TodoList, dispatch_uid="sightera.yourpackage.models.TodoList")
Ответ 4
Функции приемника должны быть такими:
def my_callback(sender, **kwargs):
print("Request finished!")
Обратите внимание, что функция принимает аргумент отправителя вместе с аргументами подстановочных ключевых слов (** kwargs); все обработчики сигналов должны принимать эти аргументы.
Все сигналы отправляют аргументы ключевых слов и могут изменить эти аргументы в любое время.
Ссылка здесь.
Ответ 5
Сигнальный хук pre_save()
действительно является отличным местом для обработки слугификации для большого количества моделей. Хитрость заключается в том, чтобы знать, какие модели требуют создания слагов, какое поле должно быть основой для значения слагов.
Для этого я использую декоратор классов, который позволяет мне отмечать модели для автоматической генерации слагов и на каком поле его основывать:
from django.db import models
from django.dispatch import receiver
from django.utils.text import slugify
def autoslug(fieldname):
def decorator(model):
# some sanity checks first
assert hasattr(model, fieldname), f"Model has no field {fieldname!r}"
assert hasattr(model, "slug"), "Model is missing a slug field"
@receiver(models.signals.pre_save, sender=model)
def generate_slug(sender, instance, *args, raw=False, **kwargs):
if not raw and not instance.slug:
source = getattr(instance, fieldname)
slug = slugify(source)
if slug: # not all strings result in a slug value
instance.slug = slug
return model
return decorator
Это регистрирует обработчик сигнала только для определенных моделей и позволяет изменять поле источника для каждой украшенной модели:
@autoslug("name")
class NamedModel(models.Model):
name = models.CharField(max_length=100)
slug = models.SlugField()
@autoslug("title")
class TitledModel(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField()
Обратите внимание, что не делается попытка сгенерировать уникальное значение слага. Это потребует проверки исключений целостности в транзакции или использования рандомизированного значения в слаге из достаточно большого пула, чтобы сделать коллизии маловероятными. Проверка исключений целостности может быть выполнена только в методе save()
, а не в перехватчиках сигналов.