This commit is contained in:
Tuna VARGI 2014-07-17 13:54:05 +00:00
commit c6a7e70eb4
7 changed files with 134 additions and 0 deletions

View File

@ -306,6 +306,32 @@ Django's regular [FILE_UPLOAD_HANDLERS] are used for handling uploaded files.
---
## Base64ImageField
An image representation for Base64ImageField
Intherited by `ImageField`
**Signature:** `Base64ImageField()`
- It takes a base64 image as a string.
- a base64 image: `data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7`
- Base64ImageField accepts only the part after base64, `R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7`
**Example:**
#serializer
class UploadedBase64ImageSerializer(serializers.Serializer):
file = serializers.Base64ImageField(required=False)
created = serializers.DateTimeField()
#use the serializer
file = 'R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='
serializer = UploadedBase64ImageSerializer(data={'created': now, 'file': file})
# Custom fields
If you want to create a custom field, you'll probably want to override either one or both of the `.to_native()` and `.from_native()` methods. These two methods are used to convert between the initial datatype, and a primitive, serializable datatype. Primitive datatypes may be any of a number, string, date/time/datetime or None. They may also be any list or dictionary like object that only contains other primitive objects.

BIN
env/share/man/man1/ipcluster.1.gz vendored Normal file

Binary file not shown.

BIN
env/share/man/man1/ipcontroller.1.gz vendored Normal file

Binary file not shown.

BIN
env/share/man/man1/ipengine.1.gz vendored Normal file

Binary file not shown.

BIN
env/share/man/man1/ipython.1.gz vendored Normal file

Binary file not shown.

View File

@ -5,19 +5,25 @@ They are very similar to Django's form fields.
"""
from __future__ import unicode_literals
import base64
import copy
import datetime
import imghdr
import inspect
import re
import uuid
import warnings
from decimal import Decimal, DecimalException
from django import forms
from django.core.files.base import ContentFile
from django.core import validators
from django.core.exceptions import ValidationError
from django.conf import settings
from django.db.models.fields import BLANK_CHOICE_DASH
from django.http import QueryDict
from django.forms import widgets
from django.utils.encoding import is_protected_type
from django.utils.translation import ugettext_lazy as _
from django.utils.datastructures import SortedDict
@ -1038,3 +1044,49 @@ class SerializerMethodField(Field):
def field_to_native(self, obj, field_name):
value = getattr(self.parent, self.method_name)(obj)
return self.to_native(value)
DEFAULT_CONTENT_TYPE = "application/octet-stream"
ALLOWED_IMAGE_TYPES = (
"jpeg",
"jpg",
"png",
"gif"
)
class Base64ImageField(ImageField):
"""
A django-rest-framework field for handling image-uploads through raw post data.
It uses base64 for en-/decoding the contents of the file.
"""
def from_native(self, base64_data):
# Check if this is a base64 string
if base64_data in validators.EMPTY_VALUES:
return None
if isinstance(base64_data, basestring):
# Try to decode the file. Return validation error if it fails.
try:
decoded_file = base64.b64decode(base64_data)
except TypeError:
raise ValidationError(_("Please upload a valid image."))
# Generate file name:
file_name = str(uuid.uuid4())[:12] # 12 characters are more than enough.
# Get the file name extension:
file_extension = self.get_file_extension(file_name, decoded_file)
if file_extension not in ALLOWED_IMAGE_TYPES:
raise ValidationError(_("The type of the image couldn't been determined."))
complete_file_name = file_name + "." + file_extension
data = ContentFile(decoded_file, name=complete_file_name)
return super(Base64ImageField, self).from_native(data)
raise ValidationError(_('This is not an base64 string'))
def to_native(self, value):
# Return url including domain name.
return value.name
def get_file_extension(self, filename, decoded_file):
extension = imghdr.what(filename, decoded_file)
extension = "jpg" if extension == "jpeg" else extension
return extension

View File

@ -1002,3 +1002,59 @@ class BooleanField(TestCase):
bool_field = serializers.BooleanField(required=True)
self.assertFalse(BooleanRequiredSerializer(data={}).is_valid())
class UploadedBase64Image(object):
def __init__(self, file=None, created=None):
self.file = file
self.created = created or datetime.datetime.now()
class UploadedBase64ImageSerializer(serializers.Serializer):
file = serializers.Base64ImageField(required=False)
created = serializers.DateTimeField()
def restore_object(self, attrs, instance=None):
if instance:
instance.file = attrs['file']
instance.created = attrs['created']
return instance
return UploadedBase64Image(**attrs)
class Base64ImageSerializerTests(TestCase):
def test_create(self):
"""
Test for creating Base64 image in the server side
"""
now = datetime.datetime.now()
file = 'R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='
serializer = UploadedBase64ImageSerializer(data={'created': now, 'file': file})
uploaded_image = UploadedBase64Image(file=file, created=now)
self.assertTrue(serializer.is_valid())
self.assertEqual(serializer.object.created, uploaded_image.created)
self.assertFalse(serializer.object is uploaded_image)
def test_validation_error_with_non_file(self):
"""
Passing non-base64 should raise a validation error.
"""
now = datetime.datetime.now()
errmsg = "Please upload a valid image."
serializer = UploadedBase64ImageSerializer(data={'created': now, 'file': 'abc'})
self.assertFalse(serializer.is_valid())
self.assertEqual(serializer.errors, {'file': [errmsg]})
def test_remove_with_empty_string(self):
"""
Passing empty string as data should cause image to be removed
"""
now = datetime.datetime.now()
file = 'R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='
uploaded_image = UploadedBase64Image(file=file, created=now)
serializer = UploadedBase64ImageSerializer(instance=uploaded_image, data={'created': now, 'file': ''})
self.assertTrue(serializer.is_valid())
self.assertEqual(serializer.object.created, uploaded_image.created)
self.assertIsNone(serializer.object.file)