mercredi 21 mai 2014

python - django ForeignKey convertir un nom de répertoire utilisable - Stack Overflow


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.




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




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.




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



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.



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



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.



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


0 commentaires:

Enregistrer un commentaire