I have a PDF model in my Django project. I want to save these files to my C: directory instead of my project directory. ( Save to C:\otc )
I don't have to file it as in the model (customer_customer_name), I just want to save it in a file named otc in C:
And How can I add a timestamp to the uploaded PDF file's name?
models.py
def customer_directory_path(self, filename):
return 'customer_{0}/{1}'.format(self.owner.customer_name, filename)
class Pdf(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=200)
pdf = models.FileField(upload_to=customer_directory_path)
type = models.CharField(max_length=200, default='Select', choices=CHOICES)
year = models.CharField(max_length=200, default='Select')
created_date = models.DateTimeField(default=datetime.now())
If you use FileSystemStorage as default file storage then upload_to is appended to MEDIA_ROOT. You need to change MEDIA_ROOT to C: if you want all upload be there or create new Storage for that field. More in doc.
created_date field should probably looks like this:
created_date = models.DateTimeField(default=datetime.now)
otherwise all rows will have same value.
then you can try:
def customer_directory_path(self, filename):
filename = "{}_filename".format(self.created_date)
return 'customer_{0}/{1}'.format(self.owner.customer_name, filename)
BTW: not sure where you got owner in that function.
EDIT:
you should be able to use also this approach if you don't want to create new Storage.
pdf = models.FileField(upload_to=customer_directory_path, storage=FileSystemStorage(location="C:"))
Related
I'm trying to generate a unique filename for the uploaded file using the Django forms. I've tried uuid_upload_path app but that app doesn't work with the form. Below is my code
Forms.py
class HelpGuideForm(forms.ModelForm):
title = forms.CharField(max_length = 50)
image = forms.ImageField(required = False)
class Meta:
model = Helpguide
fields = ['title', 'image']
Models.py
from uuid_upload_path import upload_to
class HelpguideImage(models.Model):
image = models.ImageField(upload_to = upload_to, blank=True, null=True)
I want a unique name for all uploaded files. something like sd564sadasd61.jpg. I'm using Django 2.2
In your Model you can set the upload_to of the imagefield to a function and then generate the uuid.
A very simple (untested) example:
import uuid
Class MyModel(models.Model):
def get_path(instance, filename):
extension = filename.split('.')[-1]
uuid = uuid.uuid1().hex
return f'path/to/file/{uuid}.{extension}'
image = ImageField(upload_to=get_path)
What I understand of your problem, you can set initial for FORM class when initialising it. like:
help_guide_form = HelpGuideForm(initial={'headline': uuid.uuid4().hex}, instance= Helpguide)
from django docs. Also see the initial reference.
How do I save an Image in a specific folder, depending of whom is Loggedin?
My program creates a folder for every user that registers
after they login, they are able to upload some images.
The problem is when I try to save my image, I need to specify the path where is going to be Uploaded (with the userID)
Example:
If Bob is Loggedin, you will upload the images here: space/users/bob123/example.png
Model
class StudentPhotos(models.Model):
image = models.ImageField(upload_to= ??? , default="", null=True)
image_id = models.CharField(max_length = 15, null=False, editable=False, default=id_generator, primary_key=True)
user_id = models.CharField(max_length = 15, null=False, default="")
The main reason to save it that way is to be able to bring in my admin site all images from an user
Lets say you have your model like as follows(Demonstration only):
class StudentPhotos(models.Model):
image = models.ImageField(upload_to=name)
user = models.ForeignKey(User)
Here name (upload_to=name) can be function as follows:
def name(instance, fname):
return '/'.join(instance.user.get_full_name(), fname)
I personally make use of easy-thumbnails for the purpose of having image fields in my models and I am able to use name function in the way I have given above.
Hope, you can infer some relative information and be able to come up with a better solution for your needs.
my model.py as follows,
class Employee(models.Model):
id = models.IntegerField(max_length = 6,primary_key=True,verbose_name="Employee ID")
name = models.CharField(max_length = 100,verbose_name="Name")
image = models.ImageField(upload_to = ".",blank=True,null=True)
When i try to add image in django admin, it uploads the image to /site_media/media. Here i want to replace the uploaded image name with my primary key field ID.jpeg, so that i can retrieve and show that in html pages .
Even now i can retrieve the image name because its stored in db. However for simplifying i need to customize the image name before upload. Also if the user uploads another image for same person it should overwrite the old one. At present it just changes the new name in db. But still old image is present in the media folder
You can use a callable for upload_to as follows:
def file(self, filename):
url = "./%d.JPG" % (self.id,)
return url
class Employee(models.Model):
id = models.IntegerField(max_length = 6,primary_key=True,verbose_name="Employee ID")
name = models.CharField(max_length = 100,verbose_name="Name")
image = models.ImageField(upload_to = file,blank=True,null=True)
But you will face the problem of Django not overwriting the file which can be solved by a custom storage or deleting the file.
You can use a function for upload_to;
def sample_upload_to_function(instance, filename):
extension = filename.split('.')[-1]
return "%s.%s" %(instance.id, extension)
class Employee(models.Model):
.....
image = models.ImageField(upload_to =sample_upload_to_function, blank=True, null=True)
But i don't know how to overwrite existing file. I think before save, you must delete the existing file.
In my current project I have my images stored on a s3 bucket.
I have a pre_save signal receiver to delete the actually image from the s3 bucket on the Image class.
class Image(models.Model):
name = models.CharField(max_length = 255)
caption = models.CharField(max_length = 255)
image = models.ImageField(upload_to='uploads/',blank=True,null=True)
rent_property = models.ForeignKey(RentProperty, related_name='Images')
is_main_image = models.BooleanField(default=False)
#receiver(models.signals.pre_save, sender=Image)
def auto_delete_file_on_change(sender, instance, **kwargs):
"""Deletes file from filesystem
when corresponding `MediaFile` object is changed.
"""
if not instance.pk:
return False
try:
old_file = Image.objects.get(pk=instance.pk).image
except Image.DoesNotExist:
return False
new_file = instance.image
if not old_file == new_file:
old_file.delete(save=False)
My problem is, I am using django-rest-framework, and I want to get the PATCH to work. but if I try to patch an Image description for example, it would delete the image itself. My question is, how do I write an IF that would differentiate weather or not there is a new image in the patch that needs changing , and if not, do nothing?
For models with an ImageField or FileField, I include an additional field to store the SHA-1 hash string. I've found this useful to have for many reasons:
Reducing unneeded transfers for the same file for updates (your case)
Preventing users from uploading duplicate files as new instances
Providing users with an SHA-1 hash when downloading files so they can verify the download
Doing data integrity checks on the back-end file system to verify the files have not changed
I also save the original file name in order to reproduce it for user facing views/downloads. In this way the back-end names do not matter to the users.
Here's a basic implementation based on your model:
import hashlib
from django.core.exceptions import ValidationError
from django.core.files import File
from django.db import models
class Image(models.Model):
name = models.CharField(max_length = 255)
caption = models.CharField(max_length = 255)
image = models.ImageField(upload_to='uploads/',blank=True,null=True)
original_filename = models.CharField(
unique=False,
null=False,
blank=False,
editable=False,
max_length=256)
sha1 = models.CharField(
unique=True,
null=False,
blank=False,
editable=False,
max_length=40)
rent_property = models.ForeignKey(RentProperty, related_name='Images')
is_main_image = models.BooleanField(default=False)
def clean(self):
"""
Overriding clean to do the following:
- Save original file name, since it may already exist on our side.
- Save SHA-1 hash and check for duplicate files.
"""
self.original_filename = self.image.name.split('/')[-1]
# get the hash
file_hash = hashlib.sha1(self.image.read())
self.sha1 = file_hash.hexdigest()
# Check if this file has already been uploaded,
# if so delete the temp file and raise ValidationError
duplicate_hashes = Image.objects.all().exclude(
id=self.id).values_list('sha1', flat=True)
if self.sha1 in duplicate_hashes:
if hasattr(self.image.file, 'temporary_file_path'):
temp_file_path = self.image.file.temporary_file_path()
os.unlink(temp_file_path)
raise ValidationError(
"This image already exists."
)
I have different categories like English,French and I've applied key language = models.ForeignKey(Category) I want to validate the file before it upload to disk.
I want if category is english then file upload to english/album_name if category is french then file upload to french/album_name. I've written forms.py file. But no idea. Thanks in advance
Models.py
class Artist(models.Model):
name = models.CharField(max_length=100)
slug = models.SlugField(unique = True,max_length=100,help_text="Suggested value automatically generated from name. Must be unique.")
class Album(models.Model):
name = models.CharField(max_length=100)
slug = models.SlugField(unique = True,max_length=100,help_text="Suggested value automatically generated from name. Must be unique.")
path = models.CharField(max_length=100,null=True, blank=True)
language = models.ForeignKey(Category)
albumid = models.CharField(max_length=100)
class Song(models.Model):
title = models.CharField(max_length=100)
artist = models.ManyToManyField(Artist)
music = models.ForeignKey(Music)
album = models.ForeignKey(Album)
file = models.FileField(upload_to='media/mp3_files')
forms.py
from django import forms
from db.song.models import Song
class SongAdminForm(forms.ModelForm):
class Meta:
model = Song
# No idea what to do next :-?
def clean_file(self):
file = self.cleaned_data["file"]
if file:
if file._size > 10*1024*1024:
raise ValidationError("Audio file too large ( > 10mb )")
if not file.content-type in ["audio/mpeg","audio/..."]:
raise ValidationError("Content-Type is not mpeg")
I think what you really want is to validate it after upload, but before saving it really.
When files are uploaded, they are in a temporary folder, so you can do all checks you want before saving it to the appropriate folder.
However, if you really mean pre-upload checks, you have to use Javascript (because it is client-side). But, don't forget that you should "never trust user input", and that includes what Javascript does, because user can change the Javascript code.