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

Próxima revisión
Revisión previa
wiki2:python:django:others [2019/02/09 11:49]
alfred creado
wiki2:python:django:others [2020/10/31 20:16] (actual)
Línea 1: Línea 1:
 ====== Other things for Django ====== ====== Other things for Django ======
 +===== Messages =====
  
-  * https://​simpleisbetterthancomplex.com/​tips/​2016/​09/​06/​django-tip-14-messages-framework.html+  * [[https://​simpleisbetterthancomplex.com/​tips/​2016/​09/​06/​django-tip-14-messages-framework.html|Messages framework]] 
 + 
 +===== Sessions ===== 
 +Add this to the config: 
 +<code python>​ 
 +INSTALLED_APPS = [ 
 +    ... 
 +    '​django.contrib.sessions',​ 
 +    .... 
 + 
 +MIDDLEWARE = [ 
 +    ... 
 +    '​django.contrib.sessions.middleware.SessionMiddleware',​ 
 +    .... 
 +</​code>​ 
 +To use them: 
 +<code python>​ 
 +# Get a session value by its key (e.g. '​my_car'​),​ raising a KeyError if the key is not present 
 +my_car = request.session['​my_car'​] 
 +# Get a session value, setting a default if it is not present ('​mini'​) 
 +my_car = request.session.get('​my_car',​ '​mini'​) 
 +# Set a session value 
 +request.session['​my_car'​] = '​mini'​ 
 +# Delete a session value  
 +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>​ 
 + 
 +===== Load data y dump data from DB ===== 
 +  * https://​docs.djangoproject.com/​en/​2.1/​howto/​initial-data/​ 
 + 
 +===== Upload files ===== 
 + 
 +You will start having a form: 
 +<code python>​ 
 +from django import forms 
 + 
 +class UploadFileForm(forms.Form):​ 
 +    title = forms.CharField(max_length=50) 
 +    file = forms.FileField() 
 +</​code>​ 
 + 
 +A view handling this form will receive the file data in ''​request.FILES'',​ which is a dictionary containing a key for each FileField (or ImageField, or other FileField subclass) in the form. So the data from the above form would be accessible as request.FILES['​file'​]. 
 + 
 +The **form that posted the request has the attribute** ''​enctype="​multipart/​form-data"''​. Otherwise, request.FILES will be empty. 
 + 
 +For managing this in a view: 
 +<​code>​ 
 +def upload_file(request):​ 
 +    if request.method == '​POST':​ 
 +        form = UploadFileForm(request.POST,​ request.FILES) 
 +        if form.is_valid():​ 
 +            handle_uploaded_file(request.FILES['​file'​]) 
 +            return HttpResponseRedirect('/​success/​url/'​) 
 +    else: 
 +        form = UploadFileForm() 
 +    return render(request,​ '​upload.html',​ {'​form':​ form}) 
 + 
 +def handle_uploaded_file(f):​ 
 +    with open('​some/​file/​name.txt',​ '​wb+'​) as destination:​ 
 +        for chunk in f.chunks(): ​ # Looping over UploadedFile.chunks() instead of using read() ensures that large files don’t overwhelm your system’s memory. 
 +            destination.write(chunk) 
 +</​code>​ 
 + 
 +If you’re saving a file on **a Model with a FileField**,​ using a ModelForm makes this process much easier. The file object will be saved to the location specified by the upload_to argument of the corresponding FileField when calling form.save() 
 + 
 +If you are **constructing an object manually**, you can assign the file object from request.FILES to the file field in the model: 
 +<code python>​ 
 +def upload_file(request):​ 
 +    if request.method == '​POST':​ 
 +        form = UploadFileForm(request.POST,​ request.FILES) 
 +        if form.is_valid():​ 
 +            instance = ModelWithFileField(file_field=request.FILES['​file'​]) 
 +            instance.save() 
 +            return HttpResponseRedirect('/​success/​url/'​) 
 +    else: 
 +</​code>​ 
 + 
 +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. 
 + 
 + 
 +  * ''​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. 
 + 
 +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.1549712944.txt.gz · Última modificación: 2020/05/09 09:24 (editor externo)