* [Update]

* [Update] 修改fields
This commit is contained in:
老广
2019-03-11 10:06:45 +08:00
committed by GitHub
parent c86a036ac6
commit b45b33380c
10 changed files with 304 additions and 128 deletions

View File

@@ -0,0 +1,6 @@
# -*- coding: utf-8 -*-
#
from .form import *
from .model import *
from .serializer import *

View File

@@ -0,0 +1,63 @@
# -*- coding: utf-8 -*-
#
import json
from django import forms
from django.utils import six
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext as _
from ..utils import get_signer
signer = get_signer()
__all__ = [
'FormDictField', 'FormEncryptCharField', 'FormEncryptDictField',
'FormEncryptMixin',
]
class FormDictField(forms.Field):
widget = forms.Textarea
def to_python(self, value):
"""Returns a Python boolean object."""
# Explicitly check for the string 'False', which is what a hidden field
# will submit for False. Also check for '0', since this is what
# RadioSelect will provide. Because bool("True") == bool('1') == True,
# we don't need to handle that explicitly.
if isinstance(value, six.string_types):
value = value.replace("'", '"')
try:
value = json.loads(value)
return value
except json.JSONDecodeError:
return ValidationError(_("Not a valid json"))
else:
return ValidationError(_("Not a string type"))
def validate(self, value):
if isinstance(value, ValidationError):
raise value
if not value and self.required:
raise ValidationError(self.error_messages['required'], code='required')
def has_changed(self, initial, data):
# Sometimes data or initial may be a string equivalent of a boolean
# so we should run it through to_python first to get a boolean value
return self.to_python(initial) != self.to_python(data)
class FormEncryptMixin:
pass
class FormEncryptCharField(FormEncryptMixin, forms.CharField):
pass
class FormEncryptDictField(FormEncryptMixin, FormDictField):
pass

132
apps/common/fields/model.py Normal file
View File

@@ -0,0 +1,132 @@
# -*- coding: utf-8 -*-
#
import json
from django.db import models
from django.utils.translation import ugettext_lazy as _
from ..utils import get_signer
__all__ = [
'JsonMixin', 'JsonDictMixin', 'JsonListMixin', 'JsonTypeMixin',
'JsonCharField', 'JsonTextField', 'JsonListCharField', 'JsonListTextField',
'JsonDictCharField', 'JsonDictTextField', 'EncryptCharField',
'EncryptTextField', 'EncryptMixin',
]
signer = get_signer()
class JsonMixin:
tp = None
@staticmethod
def json_decode(data):
try:
return json.loads(data)
except (TypeError, json.JSONDecodeError):
return None
@staticmethod
def json_encode(data):
return json.dumps(data)
def from_db_value(self, value, expression, connection, context):
if value is None:
return value
return self.json_decode(value)
def to_python(self, value):
if value is None:
return value
if not isinstance(value, str) or not value.startswith('"'):
return value
else:
return self.json_decode(value)
def get_prep_value(self, value):
if value is None:
return value
return self.json_encode(value)
class JsonTypeMixin(JsonMixin):
tp = dict
def from_db_value(self, value, expression, connection, context):
value = super().from_db_value(value, expression, connection, context)
if not isinstance(value, self.tp):
value = self.tp()
return value
def to_python(self, value):
data = super().to_python(value)
if not isinstance(data, self.tp):
data = self.tp()
return data
def get_prep_value(self, value):
if not isinstance(value, self.tp):
value = self.tp()
return self.json_encode(value)
class JsonDictMixin(JsonTypeMixin):
tp = dict
class JsonDictCharField(JsonDictMixin, models.CharField):
description = _("Marshal dict data to char field")
class JsonDictTextField(JsonDictMixin, models.TextField):
description = _("Marshal dict data to text field")
class JsonListMixin(JsonTypeMixin):
tp = list
class JsonStrListMixin(JsonListMixin):
pass
class JsonListCharField(JsonListMixin, models.CharField):
description = _("Marshal list data to char field")
class JsonListTextField(JsonListMixin, models.TextField):
description = _("Marshal list data to text field")
class JsonCharField(JsonMixin, models.CharField):
description = _("Marshal data to char field")
class JsonTextField(JsonMixin, models.TextField):
description = _("Marshal data to text field")
class EncryptMixin:
def from_db_value(self, value, expression, connection, context):
if value is not None:
return signer.unsign(value)
return None
def get_prep_value(self, value):
if value is None:
return value
return signer.sign(value)
class EncryptTextField(EncryptMixin, models.TextField):
description = _("Encrypt field using Secret Key")
class EncryptCharField(EncryptMixin, models.CharField):
def __init__(self, *args, **kwargs):
kwargs['max_length'] = 2048
super().__init__(*args, **kwargs)

View File

@@ -0,0 +1,41 @@
# -*- coding: utf-8 -*-
#
from rest_framework import serializers
from django.utils import six
__all__ = ['StringIDField', 'StringManyToManyField', 'ChoiceDisplayField']
class StringIDField(serializers.Field):
def to_representation(self, value):
return {"pk": value.pk, "name": value.__str__()}
class StringManyToManyField(serializers.RelatedField):
def to_representation(self, value):
return value.__str__()
class ChoiceDisplayField(serializers.ChoiceField):
def __init__(self, *args, **kwargs):
super(ChoiceDisplayField, self).__init__(*args, **kwargs)
self.choice_strings_to_display = {
six.text_type(key): value for key, value in self.choices.items()
}
def to_representation(self, value):
if value is None:
return value
return {
'value': self.choice_strings_to_values.get(six.text_type(value), value),
'display': self.choice_strings_to_display.get(six.text_type(value), value),
}
class DictField(serializers.DictField):
def to_representation(self, value):
if not value or not isinstance(value, dict):
value = {}
return super().to_representation(value)