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.
Related
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.
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'm using imagekit provided at: imagekit
So, I've defined two class model:
class Photo(models.Model):
#photo_wrapper = models.ForeignKey(PhotoWrapper, blank=True, null=True)
original_image = models.ImageField(upload_to='static/photos')
thumbnail = ImageSpec([Adjust(contrast=1.2, sharpness=1.1),
resize.Crop(50, 50)], image_field='original_image',
format='JPEG', quality=90)
num_views = models.PositiveIntegerField(editable=False, default=0)
class IKOptions:
# This inner class is where we define the ImageKit options for the model
spec_module = 'myspecs.specs'
cache_dir = 'static/photos'
image_field = 'original_image'
save_count_as = 'num_views'
class Country(models.Model):
country_name = models.CharField(max_length=250)
country_photo = models.ForeignKey(Photo, blank=True, null=True)
def __unicode__(self):
return '%s' % self.country_name
The problem is that each photo is created in the "static/photos" path.
My intent is to save the image and the thumbnail with a dynamic path, based on the country name..
For example, for the country "Argentina", the dynamic path will be "static/photos/Argentina/"
How can I accomplish that?
It looks like you're mixing two different versions of ImageKit. The newer versions (1.0+) no longer use the inner IKOptions class, so all of that is being ignored. (The save_count_as functionality was also removed.)
If you want to control the cache filename, the ImageSpec constructor accepts a cache_to kwarg which—like ImageField's upload_to—can be a callable. Here's the current documentation for cache_to:
Specifies the filename to use when saving the image
cache file. This is modeled after ImageField's ``upload_to`` and
can be either a string (that specifies a directory) or a
callable (that returns a filepath). Callable values should
accept the following arguments:
- instance -- The model instance this spec belongs to
- path -- The path of the original image
- specname -- the property name that the spec is bound to on
the model instance
- extension -- A recommended extension. If the format of the
spec is set explicitly, this suggestion will be
based on that format. if not, the extension of the
original file will be passed. You do not have to use
this extension, it's only a recommendation.
So you'll just have to create a function that accepts those arguments and returns the path you want, and use that in your model like so:
class Photo(models.Model):
thumbnail = ImageSpec(..., cache_to=my_cache_to_function)
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.