I have created a app which will upload the file at a particular location. How can I read the file uploaded after the model is saved? When I click on the file link on change_field_page it gives page not found. I'm using Django 1.2 and django-admin for this.
Here's my models.py:
class UploadClass(models.Model):
id=models.AutoField(primary_key=True)
template_name=models.ForeignKey(sas,verbose_name=ugettext_lazy('Template Name'))
sample=models.FileField(upload_to='%Y/%B/',verbose_name=ugettext_lazy('Sample'))
status=models.IntegerField(ugettext_lazy('Status'),choices=statusChoices,default=0)
created_on=models.DateTimeField(ugettext_lazy('Created on'),auto_now_add=True)
def __unicode__(self):
return (self.template_name.name)
I'm not doing anything informs.py. How can I open the file after saving the object?
One way to do this is to create a view for the 'url' and return the file. Are there any others?
In terms of the file not being linked correctly from the admin, check your MEDIA_ROOT and your MEDIA_URL point to, ultimately, the same place. Also, can you give examples of how the %Y/%B/ is working out as folder names, please? They may not be as you expect.
Related
We need to store a few smallish files to the database (yes, I'm well aware of the counterarguments, but setting up e.g. FileField to work in several environments seems very tedious for a couple of files, and having files on the database will also solve backup requirements).
However, I was surprised to find out that even though BinaryField can be set editable, Django Admin does not create a file upload widget for it.
The only functionality we need for the BinaryField is the possibility to upload a file and replace the existing file. Other than that, the Django Admin fulfills all our requirements.
How can we do this modification to Django Admin?
You will want to create a custom Widget specifically for BinaryField which has to read the file contents before putting them into the database.
class BinaryFileInput(forms.ClearableFileInput):
def is_initial(self, value):
"""
Return whether value is considered to be initial value.
"""
return bool(value)
def format_value(self, value):
"""Format the size of the value in the db.
We can't render it's name or url, but we'd like to give some information
as to wether this file is not empty/corrupt.
"""
if self.is_initial(value):
return f'{len(value)} bytes'
def value_from_datadict(self, data, files, name):
"""Return the file contents so they can be put in the db."""
upload = super().value_from_datadict(data, files, name)
if upload:
return upload.read()
And then you need to use it in admin in the following way:
class MyModelAdmin(admin.ModelAdmin):
formfield_overrides = {
models.BinaryField: {'widget': BinaryFileInput()},
}
fields = ('name', 'your_binary_file')
Note:
BinaryField doesn't have a url or a file name so you will not be able to check what's in the db
After uploading the file you will be able to see just the byte size of the value stored in the db
You might want to extend the widget to be able to download the file
by reading it's contents
I am using django-sendfile to protect certain files.
The problem is that when the file is displayed on the frontend it uses the MEDIA_ROOT location which is not where the file actually is.
The actual link (that checks permissions) that I want to use is:
http://127.0.0.1:8000/leave/supporting_doc/57
yet the link displayed is:
http://127.0.0.1:8000/media/leave/user_2/2018-09-06-logo.png
The field in the model is:
supporting_doc = models.FileField(
upload_to=user_leave_directory_path,
storage=SENDFILE_STORAGE,
blank=True,
validators=[FileExtensionValidator(ACCEPTED_FILE_TYPES)]
)
The upload to method give a link relative to MEDIA_ROOT:
def user_leave_directory_path(instance, filename):
'''Get the user directory for leave supporting document'''
# file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
return 'leave/user_'\
f'{instance.user.id}/{instance.start_date}-{filename}'
In my views.py file, there are some functions like follows:
def upload_file(request):
"""
upload a file and store it into the database,
and the file will be predicted in another view immediately.
"""
def predict(request):
"""
make prediction of the file uploaded in the 'upload_file' function.
"""
How to access the file which uploaded in upload_file function in the predict function? Here is my thought:
1. read the last row in the database, but this sounds a little silly.
2. use a cache system and retrieve the file from cache?
Is there any useful solution for this problem? please give me any hints or other resources.
Thanks for anyone's help.
As it is described here, you can acces the storage url as Follows :
Class MyModel(models.Model):
photo = models.ImageField()
model = MyModel.objects.get(pk=1) # for instance
model.photo.url
>>> 'https://media.example.com/mymodels/example_image.jpg'
I'm doing a migration from an old site to a new one, and this includes moving a lot of logos/images/PDFs etc around. On the old site I'm exporting these using a base64 encode, and I base 64 decode them on the new site. So far, so good. Everything seemed to just work.
But, for some reason the files ended up in my MEDIA_ROOT instead of in MEDIA_ROOT/. So this means there are a few thousand files in my MEDIA_ROOT, not good.
A bit of code:
ntf = NamedTemporaryFile(delete=True)
ntf.write(base64.standard_b64decode(obj['logo']))
ntf.flush()
c.logo.save('photo-{0}.img'.format(c.id), File(ntf))
In this case, c is a Django model instance, and logo is an ImageField. The definition of the Django model c:
class C(models.Model):
def file_path(self, filename=None):
return (format(self.id).join(['c_obj', '.jpg'])).lower()
name = models.CharField(_(u'name'), max_length=150)
logo = models.ImageField(_(u'logo'), upload_to=file_path, null=True, blank=True)
Anyone who can tell me what's going wrong here?
Your file_path function is not returning a directory name. It is returning 'c_obj13.jpg' (when self.id is 13). Because of this, there is no directory (note the absence of a directory seperator).
I have a userprofile of the form
class profile():
#the next line is just an abstract
profile_images='volumes/media/root/userprofile/profile_images/'
image=models.ImageField(upload_to=profile_images)
in the directory "profile_images" there are the last 5 files the user uploaded as profile images, ie:
image_1
image_2
image_3
image_4
image_5
lets say the current profile.image is image_1. now i want to allow the user to select one of the previous images. the function i wrote to change the image to the one i received from the form looks like that:
def change_profile_image(userprofile,path_to_new_image):
f = open(path_to_new_image, 'r')
userprofile.image = ImageFile(f)
userprofile.save()
as an example the user selects image_3, and after execution of that code the forementioned directory looks like that:
image_1
image_2
image_3
image_4
image_5
volumes/media/root/userprofile/profile_images/image_3
which, of course, is not what i wanted. what i want is to just change the file associated with the ImageField of my profile instance, without Django copying any files.
any ideas how to solve that?
ok, actually it's as easy as
userprofile.image=path_to_new_image
no need to worry with opening files, deleting and rewriting them.
Theoretically, you could overwrite userprofile.image.path, but it’s not too obvious how to do that.
Here is some more information.
Programmatically saving image to Django ImageField
Django: How to replace/overwrite/update/change a file of FileField?
How can I replace/override an uploaded file?