user3348051
user3348051

Reputation:

How do I customize a slug field in Django?

I've checked this but i need to concatenate contents in two fields okay, here's the question.

I have two models, brand and product which looks something like this:

Brand Model

class Brand(models.Model):
    name = models.CharField(max_length=29)
    website = models.URLField()

    def __unicode__(self):
        return self.name

Product Model

class Product(models.Model):
    brand = models.ForeignKey(Brand)
    name = models.CharField(max_length=140)
    slug = models.SlugField()

    def __unicode__(self):
        return self.name

Admin methods

from .models import Product

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    prepopulated_fields = {'slug': ('name',)}

Sample inputs on models:

**Brand**
Name: Example
Website: http://www.example.com

**Product**
Brand: Example (Selection)
Name: Product
Slug: product(prepopulated)

I want the slug to be example-product than product. How can I concatenate both the brand and name as the slug.

Thank you for any help.

Upvotes: 6

Views: 7308

Answers (3)

moonstruck
moonstruck

Reputation: 2784

Adding brand to prepopulated_fields dictionary only returns id not str/unicode value.

class ProductAdmin(admin.ModelAdmin):
    prepopulated_fields = {'slug': ('brand', 'name',)}

One way to do is adding save_model method ModelAdmin

from django.utils.text import slugify

class ProductAdmin(admin.ModelAdmin):    
    def save_model(self, request, obj, form, change):
        # don't overwrite manually set slug
        if form.cleaned_data['slug'] == "":
            obj.slug = slugify(form.cleaned_data['brand']) + "-" + slugify(form.cleaned_data['name'])
        obj.save()

Upvotes: 14

Cheng
Cheng

Reputation: 17904

You cannot. According to Django documentation:

prepopulated_fields doesn’t accept DateTimeField, ForeignKey, nor ManyToManyField fields.

Link: https://docs.djangoproject.com/en/1.8/ref/contrib/admin/

I tried:

prepopulated_fields = {'slug': ('brand', 'name')}

This would append name after brand id instead of brand name, so you get '1-product ' instead of 'example-product'


Update: saving the slug field into database and displaying the slug field in the admin page are two different things. Saving would save the string into database. But the 'prepopulated_fields' is only for showing. It only affects the look of the admin page.

Upvotes: 0

onyeka
onyeka

Reputation: 1537

You can add a slugify function on Product save (disclaimer: I haven't tried to do this with a foreign key, so I'm not 100% sure, but this method works for me, let me know if it does for you).

from unidecode import unidecode
from django.template.defaultfilters import slugify    

class Product(models.Model):
...

    def save(self):
        if not self.id: # if this is a new item
            newslug = '{0} {1}'.format(self.brand__name, self.name)  
            self.slug = slugify(unidecode(newslug))
        super(Product, self).save()

Upvotes: 3

Related Questions