Specifying dynamic file upload location - python

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)

Related

Override translation file django

I'm actually coding a web app with django and just started to use django allauth to go a bit quicker in the creation of my user interface.
I've successfully changed the design of the templates by adding the templates from their github repo to my project. But I wanted to do the same with the translation because I want my app to be in french.
So I did the same : I added the "locale" folder to my project and edited some things in the .po files but no change happened.
Does someone know what to do, like what more is needed to override the ancient traductions ? Thanks in advance.
Overriteing code is not quicker way. In Django package allauth You got evrything you need. Read documantation:
https://django-allauth.readthedocs.io/en/latest/installation.html
But if you really wanna overrite code i dont recommend to copy all of file code from library. You can Simly overrite 1 function / class. If you will do that and pass diffrent arguments you get diffrent return sounds siple. But for reall Overrite code for me is hard option that you should do only when its need
Simple way how to overrite code:
class cl():
name = "Mephju"
def function(self, arg1, arg2):
print(arg1, arg2, self.name)
class overrite_cl():
name = "Mephju"
def function(self, arg1, arg2):
print(arg1, self.name)
print(overrite_cl)
This is bad example how to make it but i wanna make you understand. While Overriteing you pass same class parrent and then type function you wanna overrite.
Ok now my code example:
enter image description here
This is from library
enter image description here
red lines is thing that i changed. So as you can see This is same function but with diffrent return. I'm still returning this to same algorythm. But now its return something diffrent.
I dont know what are you trying to make in your web app but i'm shure thing you wanna make its allredy in django allauth.

How to have the functionality of FileField's "upload_to" parameter without actually uploading anything?

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?

Django-models: use field from foreign key

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)

Django Mongodb ListField not saving or updating

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.))

converting django ForeignKey to a usable directory name

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).

Categories