Kenan
Kenan

Reputation: 141

Pass instance field to function as parameter

I have this code which generates slug for django models. I have a different model field which is passed to function for generating it from (for example- name, title)

I marked variable name by naming it HELP_HERE_INSTANCE_FIELD_PASS_TO_FUNCTION

How do I pass this "title", "name" fields that so this function will work for any field name I pass it to.

# utils.py

DONT_USE = ['create']

def random_string_generator(
        size=2, chars=string.ascii_lowercase + string.digits
):
    return ''.join(random.choice(chars) for _ in range(size))


def unique_slug_generator(instance, HELP_HERE_INSTANCE_FIELD_PASS_TO_FUNCTION, new_slug=None):
    if new_slug is not None:
        slug = new_slug
    else:
        slug = slugify(instance.HELP_HERE_INSTANCE_FIELD_PASS_TO_FUNCTION)

    Klass = instance.__class__
    qs_exists = Klass.objects.filter(slug=slug).exists()
    if qs_exists:
        new_slug = f"{slug}-{random_string_generator(size=4)}"
        return unique_slug_generator(instance, HELP_HERE_INSTANCE_FIELD_PASS_TO_FUNCTION, new_slug=new_slug)
    return slug

I will use that function here

# models.py

class Category(models.Model):
    name = models.CharField(max_length=64)
    slug = models.SlugField(unique=True, blank=True)

class Event(models.Model):
    title = models.CharField(max_length=128)
    slug = models.SlugField(unique=True, blank=True)

def event_slug_pre_save_receiver(sender, instance, *args, **kwargs):
    if not instance.slug:
        instance.slug = unique_slug_generator(
               instance, HELP_HERE_INSTANCE_FIELD_PASS_TO_FUNCTION="title"
        )


def category_slug_pre_save_receiver(sender, instance, *args, **kwargs):
    if not instance.slug:
        instance.slug = unique_slug_generator(
               instance, HELP_HERE_INSTANCE_FIELD_PASS_TO_FUNCTION="name"
        )

Upvotes: 2

Views: 717

Answers (2)

Nalin Dobhal
Nalin Dobhal

Reputation: 2342

Instead of passing the field name to the function, use the actual value you want to slugify as you are using that value for creating slug and not as the database lookup field.

def unique_slug_generator(instance, VALUE_YOU_WANT_TO_SLUGIFY, new_slug=None):
    if new_slug is not None:
        slug = new_slug
    else:
        slug = slugify(VALUE_YOU_WANT_TO_SLUGIFY)

    Klass = instance.__class__
    qs_exists = Klass.objects.filter(slug=slug).exists()
    if qs_exists:
        new_slug = f"{slug}-{random_string_generator(size=4)}"
        return unique_slug_generator(instance, VALUE_YOU_WANT_TO_SLUGIFY, new_slug=new_slug)
    return slug

call that function as:

def event_slug_pre_save_receiver(sender, instance, *args, **kwargs):
    if not instance.slug:
        instance.slug = unique_slug_generator(
               instance, instance.title
        )


def category_slug_pre_save_receiver(sender, instance, *args, **kwargs):
    if not instance.slug:
        instance.slug = unique_slug_generator(
               instance, instance.name
        )

Upvotes: 2

neverwalkaloner
neverwalkaloner

Reputation: 47354

You can use getattr method to get instance's attribute by string:

def unique_slug_generator(instance, HELP_HERE_INSTANCE_FIELD_PASS_TO_FUNCTION, new_slug=None):
    if new_slug is not None:
        slug = new_slug
    else:
        slug = slugify(getattr(instance, HELP_HERE_INSTANCE_FIELD_PASS_TO_FUNCTION))

Upvotes: 1

Related Questions