Passing a parameter to a FileField Storage's Save Method - django

So here is my situation. I have a model that I am saving, and it contains the following file:
file = models.FileField(storage=s3store, upload_to=custom_upload_to)
S3Store is a custom storage solution that I have implemented. Within that custom storage solution, I have a dictionary to all my different Amazon S3 Buckets [a dictionary with all S3BotoStorage connections]. Depending on who is uploading the file, I need to send it to it's appropriate S3BotoStorage, that is set to the appropriate bucket. I was wondering if it was possible to pass a parameter to my s3store.save() method from within my model save method?
I thought about simply appending the bucket_name to the filename, but appending & then removing would take too much calculation time no? (and memory).
Hope it makes sense!

Related

Django: Save ContentFile (or some kind of virtual file) to database

In my django app I create a string which I have to save to my database as a File.
If i understand correctly, django is supposed to automatically upload the file when I save the entry:
class Foo(models.Model):
bar1=models.ForeignKey(Table1)
bar2=models.ForeignKey(Table2)
res=models.FileField(upload_to='MYPATH')
The problem is that to create an instance of Foo, I have to first create a physical file on the server's disk which would mean two copies would be created (one by me in order to create a database entry, one by django when saving the entry).
As far as I can see, I must create the file myself in 'MYPATH' and instead of using a FileField, I have to save a reference in the database (essentially what django is doing ????). However I have doubts that this is the best method as
It doesn't strike me as Pythonesque.
I won't have access to the same methods as when using a real FileField. For instance when calling it, I won't have a FieldFile but just a reference string.
Basically, what I wanted to do was: String --> ContentFile (or some form of "virtual" file) --> Physical File handled by Django when saving entry in the database.
entry = Foo(bar1=var1, bar2=var2, res=ContentFile(XMLSTRING))
entry.save()
This doesn't work, but it shows what I want to achieve.
So, please show me one of the following three:
How to save a file to the database without physically creating it (using a ContentFile doesn't create a physical file after saving the entry which is what I want to do)
Make django not upload the given file but use the already uploaded version whilst maintaining all the methods provided by FileField
What I don't understand.
I apologize for [my english, my lack of understanding, the lack of clarity]
Anything you need to know, I'd happy to specify.
EDIT: I looked at this thread, but there, the urlretrieve creates a temp file, which is something I don't really want to do. Maybe I should be doing that, but is there a better way?

Selectively deleting images uploaded to Azure blob (Django/Python project)

In a Django (Python) project, I'm using Azure blobs to store photos uploaded by users. The code simply goes something like this:
from azure.storage.blob import BlobService
blob_service = BlobService(account_name=accountName, account_key=accountKey)
blob_service.put_blob(
'pictures',
name, # including folder
content_str, # image as stream
x_ms_blob_type='BlockBlob',
x_ms_blob_content_type=content_type,
x_ms_blob_cache_control ='public, max-age=3600, s-maxage=86400'
)
My question is: what's the equivalent method to delete an uploaded photo in my particular scenario? I'm writing a task to periodically clean up my data models, and so want to get rid of images associated to them as well.
You should be able to use:
blob_service.delete_blob(container_name, blob_name)
You can also delete an entire container:
blob_service.delete_container(container_name)
There are a few extra parameters which will be helpful to you if you're trying to delete snapshots, deal with leases, etc.
Note that put_blob() is defined in blockblobservice.py, while delete_blob() is defined in baseblobservice.py (deletes are going to be the same, whether page, block, or append blob).

How to pass dictionary or list or custom objects from feature file

If a method takes dictionary as parameter, how to pass it. Do we need to construct the dictionary from values present in feature file and pass internally to the method. Is there any direct way we can pass objects?
As far as I know, you can't pass objects in features, but you can send text and tables in the feature file. The text you send can be exploited to send JSON string of your dict/lists and further create objects using that data in step definition.

Django-rest-framework json dump

I've made a simple JSON API using django-rest-framework, and I'd like to be able to download the 5 collections as one zipfile containing the collections as JSON files. (my app requires this offline dump of data).
I'm thinking of writing a view, served at, say, /download/ that bundles up the output from all my MyModelList.as_view()s in a zip and serves it.
What is the best way of doing this? I could use urllib/Requests to query my API directly, but it seems a long way round, to invoke the whole http stack...
Many thanks!
You could use the MyModelList.as_view()(request, format="json").rendered_content you mention. Depending on your setup, you could also call a serializer directly instead of going all the way through your model. This, of course, depends on whether you do anything special in your view or whether you just pass along serialized model data.
For zipping up those files, use Python's zipfile module. See https://stackoverflow.com/a/9644831/27401 and https://stackoverflow.com/a/908293/27401 for some additional hints. A summary:
Use StringIO to create a file-like object (instead of a temporary file).
Use zipfile's .writestr('filename-in-zip.json', your_json_string) on that StringIO to add content.
When returning the zipfile as a django response, don't forget to set the Content-Disposition header as shown in https://stackoverflow.com/a/909088/27401

Customize save path for ImageField

I want to customize the folders that are used to save my images for a record...currently, I have:
original_image = models.ImageField(upload_to='photos')
But what I want to have is the images being saved to photos/<vehicle's_stock_number>/...how can I add the stock number to the end of the upload path?
Per the documentation for FileField.upload_to:
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. The two arguments that will be passed are:
instance: An instance of the model where the FileField is defined. More specifically, this is the particular instance where the current file is being attached. 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.
filename: The filename that was originally given to the file. This may or may not be taken into account when determining the final destination path.
So if you've got a model which has a stock_number attribute, you could use something like this:
def get_path(instance, filename):
return 'photos/%s/%s' % (instance.stock_number, filename)