I have an Image model. I want it to upload to a folder depending on which category the user chooses. For example if the user chooses the "apples" category I'd like it to upload to a media folder called "apples".
class Image(models.Model):
image = models.ImageField(upload_to=category)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
You can pass a callable to the category that takes as parameters self and the filename of the original file.
You thus can define this as:
from os.path import join as osjoin
class Image(models.Model):
def image_dir(self, filename):
return osjoin(str(self.category), filename)
image = models.ImageField(upload_to=image_dir)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
Note that here I assume that you have given the Category model a __str__ method. You might however change str(self.category) to for example: self.category.name for example if the Category has a name field, and you want to use that.
Related
I am trying to save an image file with the name changed to that of another field in the same form.
After some experimentation, it works well by using a handler function in the model, just when the object has been returned to the model for saving. I deconstruct the file object and can assign it a name that I want, However, I am not able to deconstruct the Charfield object and dynamically pass the first field name to the image file.
from django.db import models
import os
#handler function to customise file name.
def photo_path(instance, filename):
basefilename, file_extension= os.path.splitext(filename)
return '{add}/{room}/{basename}{ext}'.format
(add='my_Add', room="should_Be_room_type", basename= basefilename, ext= file_extension)
And the model is:
class Room(models.Model):
room_type = models.CharField( max_length=50) # i.e bedroom /living room etc
room_size = models.CharField( max_length=50)
img = models.ImageField( upload_to=photo_path, null=True, blank=True)
def __str__(self):
return self.room_type
in your case, the argument instance would be your Room instance, and you can use it to recover room_type and room_size. As the instance won't be created until after the image uploads, the only thing that won't be available on photo_path will be instance.id, but you don't need it.
Your function then, can be written as:
def photo_path(instance, filename):
basefilename, file_extension = os.path.splitext(filename)
return '{add}/{room}/{basename}{ext}'.format
(add='my_Add', room=instance.room_type, basename=basefilename, ext=file_extension)
Thanks, I ended up solving it in the view.py by using
my_room_type = request.POST['room_type']
initial_obj = form.save(commit=False)
initial_obj.save()
The idea was to get the value entered for the 'room_type' and print it on the image. It now works thanks.
Because I want the Charfield string to save my Image at specific folder. I want to transfer or extract the string from CharField in Django
I have tried the to_python method it doesn't work in class level.
class Project(models.Model):
filename = models.CharField(max_length=150)
cata = models.CharField(max_length=150)
image = models.ImageField(max_length=100, upload_to= 'ourwork/image/' + str(cata) + '/' + str(filename) , default='ourwork/default/default.png', verbose_name='图片')
def __str__(self):
return self.filename
I want to see the image I uploaded at Django Admin console to show at 'ourwork/project/image' folder
Short answer: use a callable and let the callable calculate the upload_to attribute, based on the field of the model object.
You can use a callable as FileField.upload_to attribute [Django-doc], as the documentation specifies:
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.
So we can define this as:
def our_upload_to(instance, filename):
return 'ourwork/image/{}/{}'.format(instance.cata, instance.filename)
class Project(models.Model):
filename = models.CharField(max_length=150)
cata = models.CharField(max_length=150)
image = models.ImageField(max_length=100, upload_to=our_upload_to, default='ourwork/default/default.png', verbose_name='图片')
def __str__(self):
return self.filename
We thus here calculate the upload_to parameter based on the instance (first parameter), and ignore the filename of that was originally given to the file by the user that uploaded the file.
In this model, I want to change the name of the file uploaded in ImageField
class Product(models.Model):
image = models.ImageField(upload_to=content_file_name)
name = models.CharField(max_length=100)
amount = models.PositiveIntegerField()
class Meta:
ordering = ('name',)
def __str__(self):
return self.name
To change the name of image I'm using this function
def content_file_name(instance, filename):
ext = filename.split('.')[-1]
filename = '%s.%s' % (instance.id, ext)
return os.path.join('products', filename)
but the name of my image is None, if I use other fields like 'name', it works. What should I do to change the name with id? Thanks!
The instance's id is not yet created, because the upload_to function is called before the new object is first written to the database.
In most cases, this object will not have been saved to the database yet, so if it uses the default AutoField, it might not yet have a value for its primary key field.
Emphasis from the Django docs
Two alternatives:
Use a uuid.uuid4() value, its easy to create and as unique as the pk.
Another suggestion, if you care about search engines and SEO, use a slugify(instance.name) so that your images can be easier found in the image search of search engines.
I would like to upload images to the media root based on the field values given by the Django admin user. Here is the code that I've written and I know that the upload_to parameter is causing the problem. But I don't know how to make it work.
models.py
class Info(models.Model):
file_no = models.CharField(max_length=100)
date = models.DateField()
area = models.IntegerField(default=0.00)
mouja = models.CharField(max_length=100)
doc_type_choices = (
('deed', 'Deed'),
('khotian', 'Khotian'),
)
doc_type = models.CharField(max_length=50,
choices=doc_type_choices,
default='deed')
doc_no = models.CharField(max_length=50)
def __unicode__(self):
return self.file_no
class Image(models.Model):
info = models.ForeignKey('Info')
content = models.ImageField(upload_to=self.info.mouja/self.info.doc_type)
def __unicode__(self):
return self.info.file_no
Whenever I run python manage.py makemigrations it shows NameError: name 'self' is not defined
Thanks in advance for any help!
In the upload_to keyword you would need to provide a function that you will define, for instance:
def path_file_name(instance, filename):
return '/'.join(filter(None, (instance.info.mouja, instance.info.doc_type, filename)))
class Image(models.Model):
content = models.ImageField(upload_to=path_file_name)
From Django documentation: Model field reference:
This may also be a callable, such as a function, which will be called to obtain the upload path, including the filename. This callable must be able to accept two arguments, and return a Unix-style path (with forward slashes) to be passed along to the storage system.
Within this callable, which in the particular case is path_file_name function, we build a path from the instance field which is the particular record of Image model.
The filter function removes any None items out of the list and the join function constructs the path by joining all list items with /.
Here is the original code that worked. Just in case anyone needs it.
def path_file_name(instance, filename):
return '/'.join(filter(None, (instance.info.mouja, instance.info.doc_type, filename)))
I have this model which has Image field to be uploaded. It has a foreign key reference to another class.
from django.template.defaultfilters import slugify
def upload_to(path, attribute):
def upload_callback(instance, filename):
return '%s%s/%s' % (path, unicode(slugify(getattr(instance, attribute))), filename)
return upload_callback
class Data(models.Model):
place = models.CharField(max_length=40)
typeOfProperty = models.CharField(max_length=30)
typeOfPlace = models.CharField(max_length=20)
price = models.IntegerField()
ownerName = models.CharField(max_length=80)
class ImageData(models.Model):
property = models.ForeignKey(Data, related_name='images')
image = models.ImageField(upload_to = upload_to('image/', 'ownerName'),blank=True,null=True)
def __unicode__(self):
return self.property.ownerName
I have refered this This Web Page to create a dynamic field for images to be stored.
My doubt is can I use the onerName as the attribute in (as the ownerName is in the super class) :
image = models.ImageField(upload_to = upload_to('image/', 'ownerName'),blank=True,null=True)
How does Django consider this request that is need to be served?
Please can anyone explain me this?
'ownerName' is not going to work. It's quite complicated to do the definition of what you want to save in the ImageField directly. Maybe you should do something like this:
def upload_to(path):
def upload_callback(instance, filename):
return '%s%s/%s' % (path, unicode(slugify(instance.property.ownerName), filename)
return upload_callback
If you really want to make it as dynamic as possible you have to pass something like 'property.ownerName' to the function, split the string, retrieve attrtibute property from ImageData instance and then attribute ownerName from its foreign key instance.
Though I think this makes things way to complicated and you better define extra functions for different use cases.