问题
Am using django rest framework 3.6
The frontend library I am using is x-editable
, it requires knowledge of the datatype of the field.
I am currently fetching my data using Django Rest Framework and Serializers. I have googled about Serializer Field but I have difficulty understanding if it fits my requirements. Also I have no idea how to go about testing if it fits.
Basically I have a endpoint that attempts to fetch a single instance of SomeModel and its 5 related models. /api/v1.0/shape/2508
This works okay and I get back a data structure that's like this:
{
"data": {
"art_numbers": [],
"collection": "",
"extra_number": "",
"some_related_model1": {
"finished_capacity": null,
"finished_weight": null,
"finished_width": null,
"id": 3
},
"has_associated_product_variant": false,
"id": 2508,
"another_related_model": {
"bar_height": null,
"bar_number": "",
"id": 3,
}
}
}
Is there a way for django restframework to also pass in some metadata about the related model fields? like data type?
The minimum I am looking for is to be able to get back the data type of the fields inside the related models.
I want to be able to detect numbers, normal charfield, textfield
回答1:
Django Rest Framework has metadata classes. But you can augment it with another library called drf-schema-adapter.
- pip install drf-schema-adapter which should be 0.9.43
- go to settings.py and add this
'DEFAULT_METADATA_CLASS': 'drf_auto_endpoint.metadata.AutoMetadata',
to yourREST_FRAMEWORK
settings - add in this brand new setting
DRF_AUTO_METADATA_ADAPTER = 'drf_auto_endpoint.adapters.ReactJsonSchemaAdapter'
in the same file
It should look like this:
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer',
),
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
],
'DEFAULT_METADATA_CLASS': 'drf_auto_endpoint.metadata.AutoMetadata',
'TEST_REQUEST_DEFAULT_FORMAT': 'json',
'PAGE_SIZE': 20,
'SEARCH_PARAM': 'q'
}
DRF_AUTO_METADATA_ADAPTER = 'drf_auto_endpoint.adapters.ReactJsonSchemaAdapter'
Choosing ReactJsonSchemaAdapter is a purely personal preference. You can also stick with the SimpleMetadata from DRF itself.
use something like postman to test on the same url but using OPTIONS as the method
You should get back something like this:
{
"data": {
"name": "Shape Detail",
"description": "Retrieve a shape by its id.",
"renders": [
"application/json"
],
"parses": [
"application/json",
"application/x-www-form-urlencoded",
"multipart/form-data"
],
"actions": {
"PUT": {
"id": {
"type": "integer",
"required": false,
"read_only": true,
"label": "ID"
},
"name": {
"type": "string",
"required": true,
"read_only": false,
"label": "Shape Name",
"max_length": 100
},
"name_en": {
"type": "string",
"required": false,
"read_only": false,
"label": "Shape Name [en]",
"max_length": 100
},
"name_zh_hans": {
"type": "string",
"required": false,
"read_only": false,
"label": "Shape Name [zh-hans]",
"max_length": 100
},
"serial_number": {
"type": "string",
"required": false,
"read_only": false,
"label": "Shape Number",
"max_length": 100
},
"shape_variant_number": {
"type": "string",
"required": false,
"read_only": false,
"label": "Shape Variant Number",
"max_length": 100
},
"collection": {
"type": "string",
"required": false,
"read_only": false,
"label": "Collection",
"max_length": 255
},
"qr_code": {
"type": "string",
"required": false,
"read_only": false,
"label": "QR Code",
"max_length": 255
},
"extra_number": {
"type": "string",
"required": false,
"read_only": false,
"label": "Extra Number",
"max_length": 255
},
"art_numbers": {
"type": "field",
"required": false,
"read_only": false,
"label": "Art numbers"
},
"remark": {
"type": "string",
"required": false,
"read_only": false,
"label": "Remark",
"max_length": 400
},
"has_associated_product_variant": {
"type": "field",
"required": false,
"read_only": true,
"label": "Has associated product variant"
},
"shape_benchmark": {
"type": "nested object",
"required": false,
"read_only": false,
"label": "Shape benchmark",
"children": {
"id": {
"type": "integer",
"required": false,
"read_only": true,
"label": "ID"
},
"up_spin_speed": {
"type": "string",
"required": false,
"read_only": false,
"label": "Up Spin Speed",
"max_length": 15
},
Will add more details to this should i learn more
回答2:
class ModelSerializer(serializers.ModelSerializer):
def to_representation(self, instance):
"""
add type for Related model
"""
ret = OrderedDict()
fields = [field for field in self.fields.values() if not field.write_only]
for field in fields:
try:
key = field.get_attribute(instance)
except SkipField:
continue
value = field.to_representation(key)
if isinstance(field, ModelSerializer):
value_type = {}
for k, v in value.items():
value_type[k+'_type'] = type(v).__name__
value.update(value_type)
ret[field.field_name] = value
for field in self.context:
# context defaults to including 'request', 'view' and 'format' keys.
if field not in ['request', 'view', 'format']:
ret[field] = self.context[field]
return ret
serializers.py:
class UserListSerializer(ModelSerializer):
class Meta:
model = User
fields = ('id', 'username', 'portrait', 'gender', 'tel', 'get_gender_display', 'get_full_name')
class MessageSerializer(ModelSerializer):
from_user = UserListSerializer(read_only=True)
to_user = UserListSerializer(read_only=True)
class Meta:
model = Message
fields = '__all__'
get url http://192.168.1.108/message/3
i can get:
{
"id": 3,
"from_user": {
"id": 1,
"username": "schoolms",
"portrait": "http://192.168.1.108/media/default/user/default.png",
"gender": 2,
"tel": "",
"get_gender_display": "x",
"get_full_name": "schoolms",
"tel_type": "str",
"gender_type": "int",
"id_type": "int",
"get_full_name_type": "str",
"portrait_type": "str",
"get_gender_display_type": "str",
"username_type": "str"
},
"to_user": {
"id": 2,
"username": "x1",
"portrait": "http://192.168.1.108/media/user/20171012-102543-778.png",
"gender": 2,
"tel": "",
"get_gender_display": "x",
"get_full_name": "x1",
"tel_type": "str",
"gender_type": "int",
"id_type": "int",
"get_full_name_type": "str",
"portrait_type": "str",
"get_gender_display_type": "str",
"username_type": "str"
},
"subject": "x1",
"content": "x2",
"is_read": 0,
"from_user_abandon": false,
"to_user_abandon": false,
"create_time": "2017-10-18 17:50:44",
"update_time": "2017-10-18 17:50:44"
}
来源:https://stackoverflow.com/questions/47217438/how-to-pass-information-about-the-field-data-type-to-the-frontend-when-using-dja