Herramientas de usuario

Herramientas del sitio


wiki2:python:django:others

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anterior Revisión previa
Próxima revisión
Revisión previa
wiki2:python:django:others [2020/10/09 15:08]
alfred [Upload files]
wiki2:python:django:others [2020/10/31 20:16] (actual)
Línea 27: Línea 27:
 # Delete a session value  # Delete a session value 
 del request.session['​my_car'​] del request.session['​my_car'​]
 +</​code>​
 +
 +
 +===== Sending mails =====
 +You can send mails with:
 +<​code>​
 +from django.core.mail import send_mail
 +send_mail('​subject',​ '​message',​ 'Dont Reply <​do_not_reply@domain.com>',​ ['​youremail@example.com'​])
 </​code>​ </​code>​
  
Línea 81: Línea 89:
 When a user uploads a file, Django passes off the file data to an **upload handler** – a small class that handles file data as it gets uploaded. Upload handlers are initially defined in the ''​FILE_UPLOAD_HANDLERS''​ setting. When a user uploads a file, Django passes off the file data to an **upload handler** – a small class that handles file data as it gets uploaded. Upload handlers are initially defined in the ''​FILE_UPLOAD_HANDLERS''​ setting.
  
-{{https://​docs.djangoproject.com/​en/​3.1/​ref/​files/​uploads/#​custom-upload-handlers|You can write custom handlers that customize how Django handles files}}.+ 
 +  * ''​DEFAULT_FILE_STORAGE''​ 
 +  * ''​FILE_UPLOAD_HANDLERS'':​ Which handlers will use Django when receiving a file. 
 +  * ''​FILE_UPLOAD_MAX_MEMORY_SIZE'':​ When MemoryFileUploadHandler (default) it will upload to memory the file (if it less than this value). 
 +  * ''​FILE_UPLOAD_PERMISSIONS''​ 
 +  * ''​FILE_UPLOAD_TEMP_DIR'':​ Directory to store files larger than ''​FILE_UPLOAD_MAX_MEMORY_SIZE''​ value. 
 +  * ''​MEDIA_ROOT'':​ Absolute filesystem path to the directory that will hold user-uploaded files. 
 +  * ''​MEDIA_URL'':​ URL that handles the media served from MEDIA_ROOT, used for managing stored files. It must end in a slash. 
 + 
 + 
 +[[https://​docs.djangoproject.com/​en/​3.1/​ref/​files/​uploads/#​custom-upload-handlers|You can write custom handlers that customize how Django handles files.]]
  
 By default, if an uploaded file is smaller than 2.5 megabytes, Django will hold the entire contents of the upload in memory. This means that saving the file involves only a read from memory and a write to disk and thus is very fast. However, if an uploaded file is too large, Django will write the uploaded file to a temporary file stored in your system’s temporary directory. By default, if an uploaded file is smaller than 2.5 megabytes, Django will hold the entire contents of the upload in memory. This means that saving the file involves only a read from memory and a write to disk and thus is very fast. However, if an uploaded file is too large, Django will write the uploaded file to a temporary file stored in your system’s temporary directory.
  
 +Sometimes particular views require **different upload behavior**. In these cases, you can override upload handlers on a per-request basis by modifying ''​request.upload_handlers''​.
  
 +By default Django stores files locally, using the MEDIA_ROOT and MEDIA_URL settings. ​
 +
 +When you use a FileField or ImageField, Django provides a set of APIs you can use to deal with that file.
 +
 +<code python>
 +class Car(models.Model):​
 +    name = models.CharField(max_length=255)
 +    price = models.DecimalField(max_digits=5,​ decimal_places=2)
 +    photo = models.ImageField(upload_to='​cars'​)
 +
 +car = Car.objects.get(name="​57 Chevy"​)
 +car.photo
 +# <​ImageFieldFile:​ cars/​chevy.jpg>​
 +car.photo.name
 +# '​cars/​chevy.jpg'​
 +car.photo.path
 +# '/​media/​cars/​chevy.jpg'​
 +car.photo.url
 +# '​http://​media.example.com/​cars/​chevy.jpg'​
 +</​code>​
 +
 +You can change the path in this way:
 +<code python>
 +>>>​ import os
 +>>>​ from django.conf import settings
 +>>>​ initial_path = car.photo.path
 +>>>​ car.photo.name = '​cars/​chevy_ii.jpg'​
 +>>>​ new_path = settings.MEDIA_ROOT + car.photo.name
 +>>>​ # Move the file on the filesystem
 +>>>​ os.rename(initial_path,​ new_path)
 +>>>​ car.save()
 +>>>​ car.photo.path
 +'/​media/​cars/​chevy_ii.jpg'​
 +>>>​ car.photo.path == new_path
 +True
 +</​code>​
 +
 +To manipulate images:
 +<code python>
 +>>>​ from PIL import Image
 +>>>​ car = Car.objects.get(name='​57 Chevy'​)
 +>>>​ car.photo.width
 +191
 +>>>​ car.photo.height
 +287
 +>>>​ image = Image.open(car.photo)
 +# Raises ValueError: seek of closed file.
 +>>>​ car.photo.open()
 +<​ImageFieldFile:​ cars/​chevy.jpg>​
 +>>>​ image = Image.open(car.photo)
 +>>>​ image
 +<​PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=191x287 at 0x7F99A94E9048>​
 +</​code>​
 +
 +Django delegates decisions about how and where to store files to a file **storage system**. This is the object that actually understands things like file systems, opening and reading files, etc. The default file storage is given by the ''​DEFAULT_FILE_STORAGE''​ setting.
 +
 +You can write your [[https://​docs.djangoproject.com/​en/​3.1/​howto/​custom-file-storage/​|own file storage]].
 +
 +You can create an instance of some custom file storage class, or – often more useful – you can use the global default storage system:
 +<​code>​
 +>>>​ from django.core.files.base import ContentFile
 +>>>​ from django.core.files.storage import default_storage
 +>>>​ path = default_storage.save('​path/​to/​file',​ ContentFile(b'​new content'​))
 +>>>​ path
 +'​path/​to/​file'​
 +>>>​ default_storage.size(path)
 +11
 +>>>​ default_storage.open(path).read()
 +b'new content'​
 +>>>​ default_storage.delete(path)
 +>>>​ default_storage.exists(path)
 +False
 +</​code>​
 +
 +The following code will store uploaded files under /​media/​photos regardless of what your MEDIA_ROOT setting is:
 +<code python>
 +from django.core.files.storage import FileSystemStorage
 +from django.db import models
 +
 +fs = FileSystemStorage(location='/​media/​photos'​)
 +
 +class Car(models.Model):​
 +    ...
 +    photo = models.ImageField(storage=fs)
 +</​code>​
 +
 +You can use a callable as the storage parameter for FileField or ImageField. This allows you to modify the used storage at runtime, selecting different storages for different environments,​ for example:
 +<code python>
 +def select_storage():​
 +    return MyLocalStorage() if settings.DEBUG else MyRemoteStorage()
 +
 +class MyModel(models.Model):​
 +    my_file = models.FileField(storage=select_storage)
 +</​code>​
 +
 +==== For using S3 or an alterantive service ====
 +
 +You need the ''​boto3''​ and ''​django-storages''​ packages.
 +
 +An example of settings would be...
 +<​code>​
 +AWS_ACCESS_KEY_ID = ''​
 +AWS_SECRET_ACCESS_KEY = ''​
 +AWS_STORAGE_BUCKET_NAME = '​codi.coop.test'​
 +AWS_S3_CUSTOM_DOMAIN = f'​s3.wasabisys.com/​{AWS_STORAGE_BUCKET_NAME}'​
 +AWS_S3_ENDPOINT_URL = '​https://​s3.wasabisys.com'​
 +AWS_DEFAULT_ACL = '​public-read'​
 +DEFAULT_FILE_STORAGE = '​cc_lib.storages.MediaStorage'​
 +EXTERNAL_MEDIA_PATH = '​fok/​media'​
 +MEDIA_FILE_OVERWRITE = True
 +# AWS_S3_OBJECT_PARAMETERS = {'​CacheControl':​ '​max-age=86400',​}
 +</​code>​
 +
 +Being the ''​cc_lib.storages.MediaStorage''​ the next:
 +<code python>
 +from storages.backends.s3boto3 import S3Boto3Storage
 +from django.conf import settings
 +
 +
 +class MediaStorage(S3Boto3Storage):​
 +    location = settings.EXTERNAL_MEDIA_PATH
 +    file_overwrite = settings.MEDIA_FILE_OVERWRITE
 +</​code>​
 +
 +With this you could create other storages like ''​PrivateMediaStorage''​ and use it like this:
 +<code python>
 +class Document(models.Model):​
 +    uploaded_at = models.DateTimeField(auto_now_add=True)
 +    upload = models.FileField()
 +
 +
 +class PrivateDocument(models.Model):​
 +    uploaded_at = models.DateTimeField(auto_now_add=True)
 +    upload = models.FileField(storage=PrivateMediaStorage())
 +    user = models.ForeignKey(User,​ related_name='​documents'​)
 +</​code>​
 +
 +==== So... ====
 +
 +  - Install boto3 and django-storages.
 +  - Create your own MediaStorage.
 +  - Add the settings.
 +  - Configure models.
 +  - Remind that forms in template must have the attribute ''​enctype=“multipart/​form-data”''​.
 +
 +
 +==== Notes ====
 +<code python>
 +def upload_path(instance,​ filename):
 +    if instance.type == Resource.ResourceType.PROFILE_PICTURE.value:​
 +        return f'​authors/​{instance.owner.uuid}/​avatars/​{instance.uuid}.png'​
 +    elif instance.type == Resource.ResourceType.ZINE_COVER.value:​
 +        return f'​zines/​{str(instance.related_to)}/​cover.jpg'​
 +</​code>​
wiki2/python/django/others.1602256086.txt.gz · Última modificación: 2020/10/09 16:08 (editor externo)