[Django]-Populating django field with pre_save()?

114πŸ‘

βœ…

Most likely you are referring to django’s pre_save signal. You could setup something like this:

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)

If you dont include the sender argument in the decorator, like @receiver(pre_save, sender=MyModel), the callback will be called for all models.

You can put the code in any file that is parsed during the execution of your app, models.py is a good place for that.

31πŸ‘

@receiver(pre_save, sender=TodoList)
def my_callback(sender, instance, *args, **kwargs):
    instance.slug = slugify(instance.title)
πŸ‘€Leandro Souza

19πŸ‘

you can use 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") 
πŸ‘€Eyal Ch

16πŸ‘

The pre_save() signal hook is indeed a great place to handle slugification for a large number of models. The trick is to know what models need slugs generated, what field should be the basis for the slug value.

I use a class decorator for this, one that lets me mark models for auto-slug-generation, and what field to base it on:

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, weak=False)
        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

This registers a signal handler for specific models only, and lets you vary the source field with each model decorated:

@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()

Note that no attempt is made to generate a unique slug value. That would require checking for integrity exceptions in a transaction or using a randomised value in the slug from a large enough pool as to make collisions unlikely. Integrity exception checking can only be done in the save() method, not in signal hooks.

-4πŸ‘

Receiver functions must be like this:

def my_callback(sender, **kwargs):
    print("Request finished!")

Notice that the function takes a sender argument, along with wildcard keyword arguments (**kwargs); all signal handlers must take these arguments.

All signals send keyword arguments, and may change those keyword arguments at any time.

Reference here.

πŸ‘€Rockallite

Leave a comment