6

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.

Community
  • 1
  • 1

3 Answers3

14

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()
moonstruck
  • 2,729
  • 2
  • 26
  • 29
3

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()
onyeka
  • 1,517
  • 13
  • 18
  • I already had it installed for another app so it was not an issue for me to use it here, however, it's optional. – onyeka May 11 '15 at 15:41
0

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.

Cheng
  • 16,824
  • 23
  • 74
  • 104
  • but there must be some way, insert the slug field with a concatenated string with the save function, anyway? (`def save(self, *args, **kwargs):`) ?? –  May 11 '15 at 14:02
  • @John The way of how prepopulated_fields works is defined by a javascript file called prepopulate.js. It simply pulls the value stored in the value attribute of the option tag of the brand dropdown list and put it into the slug textbox. It has nothing to do with the `save()` method which saves a record into the database. They are two different things. – Cheng May 11 '15 at 14:13
  • I mean to replace the 'dummy slug' by js on the slugbox, just before the model object being saved, You know js or vbs or even python can process the code but only saved when the `save()` method is called, I asked to modify the save method well and we care about the database not much about the admin. ;) –  May 11 '15 at 14:49
  • @John It is really hard to understand what you are asking. If the answer below answers your question, great. But what is weird is that the information contained in the answer below is already in the link in your original post. Also, your line of `prepopulated_fields = {'slug': ('name',)}` is a completely misdirection of what you are really asking. Anyways, ask a more concise question next time. – Cheng May 12 '15 at 06:27