I'm working on an image gallery project in DJango, just for the sake of it. And well, I have a class named Gallery and a class named ImageGallery.
The class named gallery would look like this:
class Gallery(models.Model):
gallery = models.ForeignKey(Gallery, related_name="parent_gallery")
title = models.CharField(max_length=200)
folder = models.CharField(max_length=200) # ex: images/galleries/slugify(self.title)
class ImageGallery(models.Model):
gallery = models.ForeignKey(Gallery, related_name="parent_gallery")
title = models.CharField(max_length=200)
image = models.ImageField(upload_to=self.gallery.folder)
Well, the last line of code is what I want to know if its possible or any other fine replacement for it.
In the DJango-admin I want to be able to add records for the table ImageGallery and when selecting the Gallery I would like to use, the images to be saved to the folder specified in gallery.folder field.
What's the best way to go around this? I haven't completed writing the two classes but I doubt they're gonna work like this. Thank you in advance. :-)
The FileField.upload_to is defined as follows
This attribute provides a way of setting the upload directory and file
name, and can be set in two ways. In both cases, the value is passed
to the Storage.save() method. ... upload_to may also be a callable,
such as a function. This will be called to obtain the upload path,
including the filename. This callable must accept two arguments and
return a Unix-style path (with forward slashes) to be passed along to
the storage system. The two arguments are:
But self.gallery.folder isn't a callable. What you need is to setup a function along the lines given in that example
def get_upload_path(instance, filename):
return '{0}/{1}'.format(instance.gallery.folder, filename)
And your model will change to
image = models.ImageField(upload_to=get_upload_path)
Related
I have a model like this:
class Sample(models.Model):
audio = models.FileField()
that I instantiate in the view like this:
sample = Sample()
sample.audio = 'audio/sample.mp4'
However, I would like to avoid having to provide the audio/ part of the filepath in the view whenever I create an object of this class, and have it defined in the model instead.
I could add upload_to parameter like this:
class Sample(models.Model):
audio = models.FileField(upload_to='audio')
but it will only work when something is actually uploaded, which is not my case. My files will already sit in the MEDIA_ROOT/audio folder.
How can I avoid providing such full path for a media file whenever I create an object from model?
So, I just started learning Django and I wanted to make an app. It's a simple app and I've just initialized my admin view and then I have a model named "Book". It's just like information about a book. The user can enter book name, author, description and upload a book cover image.
I got this working without a hiccup. But, currently, the image is being saved in the "/media" folder, because that's what I specified in the MEDIA_ROOT of the settings file (which is totally fine). Now, what I want is that instead of this in my models.py, it gets saved to it's own directory. For example :
Book Name : If god was a banker
I want the cover image to be saved in "/media/albums/If God Was A Banker".
How can I do this? I looked into the "upload_to" attribute of the "FileField". So, I tried something like this :
book_name = models.CharField(max_length=500, allow_blank=False,trim_whitespace=True)
comic_image = models.FileField(upload_to='%s/' % book_name)
and of course this didn't work, as book_name didn't return the str type (I knew it'll go wrong though). So, how can I get this to work? anything I'm missing or anything that I could do to achieve my goal?
upload_to argument can be callable.
So you can define function like this:
def upload_location(instance, filename):
return '{}/{}'.format(instance.book_name, filename)
and then use this function in model:
comic_image = models.FileField(upload_to=upload_location)
I'm trying to dynamically zip audio files that are linked using django-zipview. However I do not seem to be able to feed it the correct inputs.
Sounds have a file and sounds can be a part of a release or many releases. I would like to (for now at least) dynamically serve zip files containing all sounds in a release when the user hit's the url: url(r'^release/(?P<slug>[a-zA-Z0-9_-]+)/download$', views.ReleaseArchiveView.as_view(), name='release_download'), (The URL works fine)
Models.py (irrelevant fields removed)
class Release(models.Model):
sound = models.ManyToManyField(Sound)
release_title = models.CharField(max_length=64)
slug = AutoSlugField(populate_from='release_title',unique=True)
class Sound(models.Model):
sound_title = models.CharField(max_length=64)
file = models.FileField(upload_to=upload_path,blank=True)
slug = AutoSlugField(populate_from=('sound_title'),unique=True)
Views.py
class ReleaseArchiveView(BaseZipView):
model = Release
def get_files(self):
release = Release.objects.get(slug=self.kwargs['slug'])
return Sound.objects.filter(release__slug=release)
According to the documentation django-zipview simply needs a list of the filefields from Sounds. However I cannot find the correct query to allow me to pass this. At present I am simply being returned an empty zip file.
How can I pass a list of FileFields in the manner that django-zipview is expecting?
You just need to have a look again at the django-zipview page on GitHub that you linked to, where they provide exactly the example you need:
class ReleaseArchiveView(BaseZipView):
model = Release
def get_files(self):
sounds = Sound.objects.filter(release__slug=self.kwargs.get('slug'))
return [s.file.file for s in sounds if s.file.name]
You were missing the last part, where they return a list of file objects.
Also your code here didn't really make sense I think:
release = Release.objects.get(slug=self.kwargs['slug'])
return Sound.objects.filter(release__slug=release)
...you were passing a Release instance as the slug value, when I guess you really meant release.slug. But anyway, it appears you have release as a foreign key on the Sound model so you don't need to get the release first.
return Sound.objects.filter(release__slug=release)
Returns the entire queryset. If you want to return just the file names, you will have to return just the values:
return list(Sound.objects.filter(release__slug= self.kwargs['slug']).values_list('file', flat=True))
Which will return a list of file names
see values_list docs
I am starting to create a webapp using Django and MongoDB. Everything is working fine when I create a model and save it into the Database. Now, I do a "Class.objects.get()" to get the object I need from my DB and I have one field called "media" which is a ListField(). I had tried doing either:
Concert.media.append(list)
or
Concert.media.extend(list)
and then
Concert.save()
This is my "Concert" object in my models.py:
class Concert(models.Model):
main_artist = models.CharField(max_length=50)
concert_id = models.AutoField(primary_key=True)
openers = ListField(EmbeddedModelField('Opener'))
concert_date = models.DateField()
slug = models.SlugField(unique=True)
media = ListField()
And when I go to see the results in does not update the object. No values where saved. If someone can help me I going to give a super cyber fist bump.
Concert is a class, not an instance. You can't save a class. You need to make an instance of the class and save that. Something like
c = Concert()
c.media.append(list)
c.save()
(btw, just as a note, list is a bad variable name because list is a type in python. Never use types as variable names (though everyone is guilty of this at one point or another, including me.))
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).