How to properly save instance of FileField in Django - django

Im hoping someone can tell me what I am doing wrong and point me in the right direction.
So, I am creating an array of Model objects and then doing a bulk_create at the end to save them to the database. The one thing I am having an issue with is after I added the the FileField I cannot exactly how I need to associate data with that field. The files don't end up in the upload_to folder set nor do they end up being associated with the record itself. Id also add that I am using PyPDf2 to create the PDF files before trying to associate them to an instance of my model.
So to give you an idea on what I am trying to do. I am running this code to create the PDFs initially.
if pdf_file_name is not None:
num_pages_current_doc = page['pageRange'][-1]
input_pdf = PdfFileReader(open(pdf_file_name, 'rb'))
output_pdf = PdfFileWriter()
for _ in range(num_pages_current_doc):
output_pdf.addPage(input_pdf.getPage(page_counter))
page_counter += 1
with open(str(uuid.uuid4())+'.pdf', 'wb') as output:
output_pdf.write(output)
logging.info(f'Wrote filename: { output.name }')
The saved file I then want to associated with a model instance below this, the code looks something like this:
document = document(
location=location,
Field2=Field2, etc etc .....
pdf = ???
Im unsure how to set the field for that pdf part, Ive tried using the File() method on it. Tried putting just output.name for the field, Im not sure how to go about making this work.
Could anyone give me some insight?
Thanks!

See the FieldFile.save(name, content, save=True) method in django docs. https://docs.djangoproject.com/en/3.2/ref/models/fields/#filefield-and-fieldfile

Related

How to use objects.create to add a file field from dataframe.to_csv?

I have used this code to try to add a dataframe.to_csv to a django db FileField, but it only works when I dont specify its path, so anyone know how to overcome this, I must specify its path and name it.
Thats my code
df = pd.DataFrame(profile_names,
columns=['username', 'followers', 'tweets', 'hashtags', 'MostRecent'])
Scrape.objects.create(
user=request.user.profile,
name=keyword,
csvfile=df.to_csv(f'./static/assets_new/CSV/{request.user} - {keyword}.csv')
)
Im trying to add a csv file to django db filefield, but nothing gets added instead

Programmatically saving image to Django ImageField returning 404 in production

I have a Django app where users can upload images and can have a processed version of the images if they want. and the processing function returns the path, so my approach was
model2.processed_image = processingfunction( model1.uploaded_image.path)
and as the processing function returns path here's how it looks in my admin view
not like the normally uploaded images
In my machine it worked correctly and I always get a 404 error for the processed ones while the normally uploaded is shown correctly when I try to change the url of the processed from
myurl.com/media/home/ubuntu/Eyelizer/media/path/to/the/image
to
myurl.com/media/path/to/the/image
so how can I fix this ? is there a better approach to saving the images manually to the database ?
I have the same function but returns a Pil.image.image object and I've tried many methods to save it in a model but I didn't know how so I've made the function return a file path.
I think the problem is from nginx where I define the media path.
should/can I override the url attribute of the processedimage?
making something like
model.processed_image.url = media/somefolder/filename
Instead of using the PIL Image directly, create a django.core.files.File.
Example:
from io import BytesIO
from django.core.files import File
img_io = BytesIO() # create a BytesIO object to temporarily save the file in memory
img = processingfunction( model1.uploaded_image.path)
img.save(img_io, 'PNG') # save the PIL image to the BytesIO object
img_file = File(thumb_io, name='some-name.png') # create the File object
# you can use the `name` from `model1.uploaded_image` and use
# that above
# finally, pass the image file to your model field
model2.processed_image = img_file
To avoid repetition of this code, it would be a good idea to keep this code in processingfunction and return the File object directly from there.
My approach is a bit different from #Xyres's, I thought xyres's would make a duplicate of the existing image and create a new one and when I tried overriding the URL attribute it returned an error of
can't set the attribute
but when I saw this question and this ticket I tried making this and it worked
model2.processed_image = processingfunction(model1.uploaded_image.path)
full_path = model2.processed_image.path
model2.processed_image.name = full_path.split('media')[1]
so that explicitly making the URL media/path/to/image and cut out all of the unneeded parts like home/ubuntu and stuff

How to store a file as a string in a model text field?

I am pretty new to Django. I need some help.
I am working on an admin page that allows me to edit objects. My model has a text field that I want to fill with a file contents which will be uploaded with a FileInput widget in a form.
So I want to read the file contents, put it in a string and store it in the model text field. Therefore it should be saved in the database.
Any help with this? I dont know how to get the file , read it and store it in my model as string. I am using a ModelAdmin btw.
First off, you might want to just use a model.FileField (https://docs.djangoproject.com/en/2.0/ref/models/fields/#filefield). The database only has to store a path to the file, instead of the entire contents of the file. You might not want to store the contents of a file directly in the database, especially if its a large file.
But if you do want to read a file in to your model. Try something along the lines of:
models.py
class SomeModel(Model):
textfield = TextField()
views.py or whatever script you are calling
with open('data.txt', 'r') as myfile:
data=myfile.read()
newmodel = SomeModel()
newmodel.textfield = data
newmodel.save()

Saving image file field manually in django

I am trying to save a preview image generated by "preview_generator" Python app.
But I am getting IntegrityError duplicate key value violates unique constraint "users_material_pkey". I've tried many things but nothing seems to be working.
If I call super at the end of save I don't get material_file url or path.
remove this line material = self in your code and use below way
obj = super(Material, self).save(force_update=False, using=None,update_fields=None)
material = obj

File upload after model save on Django admin

I am using a file upload in my Django model like this :
def upload_path(self, filename):
return 'upload/actualities/%s/%s' % (self.id, filename)
photo = models.ImageField(upload_to=upload_path)
and my adminModel is :
from actualities.models import *
from django.contrib import admin
class ActualityAdmin(admin.ModelAdmin):
class Media:
js = ('/static/js/tiny_mce/tiny_mce.js', '/static/js/textareas.js')
admin.site.register(Actuality, ActualityAdmin)
Everything works fine except when i edit mu model because it has an id. But when I create it, the file upload happens before the model saving... So i put my file in /media/actualities/None/filename.jpg, and I want /media/2/filename.jpg
How can I force to make the file upload after the model saving?
Thank you!!!
You will probably want to override the Model's save() method, and maybe come up with a custom "don't do anything" UploadHandler, then switch back to the original one and call save again.
https://docs.djangoproject.com/en/dev/topics/http/file-uploads/
https://docs.djangoproject.com/en/dev/topics/db/models/
What I would do in this situation however, is make a custom upload handler that saves the file off into some temp space. Then I'd override the save method (in a mixin or something) that moves the file from temp to wherever you wanted it.
#Tomek's answer is also another way. If you have your model generate it's own id, then you can use that.
A second to last suggestion which is what I do with my photo blog is instead of saving all the images in a directory like media/2/filename.jpg I save the image by date uploaded. 2011/10/2/image.jpg This kind of helps any directory from getting too unwieldy.
Finally, you could hash the file names and store them in directories of hash name to kind of equally spread out the images in a directory.
I've picked the date style because that's meaningful for me with that project. Perhaps there is another way you can name an image for saving that would mean something more than "model with id 2's pics" that you could use for this problem.
Good Luck!
As workaround, try generating UUID for file name (instead of using self.id).