1

I have two models. Basically, I am extending from this discussion: Multiple images per Model I would like to get the value of the machine_name of the Design model and use it in creating a path for the ImageField upload_to in the DesignImage model. Something to the effect of: image = models.ImageField(upload_to='designs/' + design.get_machine_name + '/images')

This is producing the following error: AttributeError: 'ForeignKey' object has no attribute 'get_machine_name'.

I hope the code below is clear.

from django.db import models
from django.db.models.fields.related import ManyToManyField
from django.template.defaultfilters import slugify

class Design(models.Model):
    name = models.CharField(max_length=30, help_text='Name of the design.')
    machine_name = models.SlugField(editable=False)

    def save(self, *args, **kwargs):
        self.machine_name = slugify(self.name)
        super(Design, self).save(*args, **kwargs)

    def get_machine_name(self):
        return self.machine_name

    def __unicode__(self):
        return self.name

class DesignImage(models.Model):

    def get_upload_dir(self):
        return 'designs/' + self.design.machine_name + '/images'

    design = models.ForeignKey(Design, related_name='images')
    caption = models.CharField(max_length=100)
    image = models.ImageField(upload_to='designs/' + design.get_machine_name + '/images')

    def __unicode__(self):
        return self.caption

I have included the following code in case it may be useful:

from designs.models import *
from django.contrib import admin

class DesignImageInline(admin.TabularInline):
    model = DesignImage
    extra = 3 # number of extra inline form fields to display

class DesignAdmin(admin.ModelAdmin): 
    inlines = [ DesignImageInline, ]

admin.site.register(Design, DesignAdmin)
admin.site.register(DesignImage)
Community
  • 1
  • 1
Justin M
  • 1,065
  • 2
  • 10
  • 15
  • you should change the title to reflect the actual problem "using foreign key properties in a ImageField upload" or something like that – Rob Osborne Aug 04 '11 at 13:47

2 Answers2

2

In case the location an ImageField is uploaded to depends on the instance (as it does here), the upload_to argument can be a callable instead of a string, in which it will be passed the current instance and the filename. You need something like this:

import os 

def upload_to(instance, filename):
    return os.path.join('designs', instance.design.machine_name, 'images', filename)

...
    image = models.ImageField(upload_to=upload_to)
Ismail Badawi
  • 36,054
  • 7
  • 85
  • 97
1

The problem is in this line:

image = models.ImageField(upload_to='designs/' + design.get_machine_name + '/images')

The field design is not defined at "compile time", it's another field in the model.

You will need to apply that at runtime in what every form you are using to edit.

Rob Osborne
  • 4,897
  • 4
  • 32
  • 43
  • Ah, thank you for the insight. isbadawi's solution worked to apply this nicely. – Justin M Aug 03 '11 at 02:36
  • I will, most definitely. I just don't have the required 15 reputation points (yet), but I will keep these posts in mind. – Justin M Aug 04 '11 at 06:30