views:

201

answers:

3

Hello, I'm working on a django app where the user will be able to upload documents of various kinds. The relevant part of my models.py is this:

class Materials(models.Model):
    id = models.AutoField(primary_key=True)
    id_presentations = models.ForeignKey(Presentations, db_column='id_Presentations', related_name = "materials_id_presentations") # Field name made lowercase.
    materialpathname = 'documents/'
    materialpathname += str(id_presentations)
    document = models.FileField(db_column='Document', upload_to = materialpathname) # Field name made lowercase.
    docname = models.CharField(max_length=40, db_column='DocName') # Field name made lowercase.
    class Meta:
        db_table = u'Materials'

My intention is for it to save the documents associated with a given presentation, in a subdirectory with the id number for that presentation (so if "Very Important Presentation" is on the database with id 3, it should store the associated materials at the location settings.MEDIA_ROOT/documents/3/whateverdocname.txt ).

However, while the above code "works", it creates a subdirectory that, instead of being named "3", is named <django.db.models.fields.related.ForeignKey object at 0x8e358ec>, or that kind of thing. I've tried using "id_presentations.name", "id_presentations.value", etc. but these attributes don't seem to exist. I can't seem to find a place where it gives a way to get at the integer value of the ForeignKey field, so that I can convert it to a string and use it as a subdirectory name.

Any help is greatly appreciated.

A: 

Provided that the "name" property is defined on your Presentation model, if you're working with a specific instance of the model then what you want should work. Like this:

from models import Materials
obj = Materials.objects.get([some criteria here])
name = obj.id_presentation.name

If you wanted to abstract that to a method on your model, you could do this:

class Materials(models.Model):
    def id_presentation_name(self):
        return self.id_presentation.name

If you want the database id of the object, you can access either object.id or object.pk.

Gabriel Hurley
A: 

Note: you can always find out what attributes and methods are available on an object in python by calling dir(object).

Gabriel Hurley
+1  A: 

As of Django 1.0, the upload_to argument to FileFields can be a callable. If I'm understanding your intentions correctly, something like this should do the trick:

def material_path(instance, filename):
    return 'documents/%d' % instance.id_presentations.id

class Materials(models.Model):
    id_presentations = models.ForeignKey(Presentations)
    document = models.FileField(upload_to=material_path)
    docname = models.CharField(max_length=40)

That model has been simplified a little bit, but hopefully it illustrates the solution. If upload_to is a callable, then every time a file is uploaded Django will call the function, passing it two arguments: the instance to which the file was uploaded is attached and its original filename. You can generate the file path you want by pulling the ID of the presentation off of the instance in question.

More info: http://docs.djangoproject.com/en/dev/ref/models/fields/#filefield

Will McCutchen
Thanks, both for your example and the link (don't know how I missed it). Here's what ended up working:def material_path(instance, filename): return 'documents/%d/%s' % (instance.id_presentations.id, filename)(same as yours except adds filename to end of material_path)This ends up saving to [MEDIA_ROOT]/documents/4/somefile.txt, if the document somefile.txt is associated with the presentation that has id=4.
rossdavidh