Package: drf-react-template-framework
Django Rest Framework React Template FrameworkDjango Rest Framework React Template Framework is a Python package that plugs intoDjango Rest Frameworkto generate json schemas forreact-jsonschema-form. The concept is similar to the DRFHTMLFormRenderer, but specifically designed forReactfrontends.Installationpip install drf-react-template-frameworkQuick StartSee/examplefor a complete simple example.serializers.py:fromrest_frameworkimportserializersclassChoiceSerializer(serializers.ModelSerializer):choice_text=serializers.CharField()votes=serializers.IntegerField()classMeta:fields=('choice_text','votes')viewsets.py:fromrest_framework.mixinsimportRetrieveModelMixinfromdrf_react_template.mixinsimportFormSchemaViewSetMixinclassChoiceViewSet(RetrieveModelMixin,FormSchemaViewSetMixin,):queryset=models.Choice.objects.all()serializer_class=serializers.ChoiceSerializerNow when the retrieve endpoint is called,FormSchemaViewSetMixinwill update the response
to include aserializerobject in the json, while the original payload is sorted informData.Inside theserializerobject, two fieldsschemaanduiSchemacontain the objects which
can be used insidereact-jsonschema-form.DocumentationWhile the above quick start is useful for super simple cases,
the framework has a large number of additional parameters which can be used to customize behaviour.ViewsetAll viewsets must inherit fromdrf_react_template.mixins.FormSchemaViewSetMixin.
This class inherits from the
DRFGenericViewSet,
while additionally providing customfinialize response functionalityand the additional endpoint:GET */create/
>> {'serializer': ..., 'formData': {}}Which can be used to generate an empty form for create.The only other specific customization that can be applied in the viewset is different
serializers for different endpoints. For example,updateactions often show a subset of fields;
as such it is possible to overrideget_serializer_classto return the specific form required.For example:# serializers.pyclassChoiceSerializer(serializers.ModelSerializer):choice_text=serializers.CharField()votes=serializers.IntegerField()classMeta:fields=('choice_text','votes')classChoiceUpdateSerializer(serializers.ModelSerializer):choice_text=serializers.CharField()classMeta:fields=('choice_text',)# viewsets.pydefget_serializer_class(self):ifself.action=='update':returnChoiceUpdateSerializerreturnChoiceSerializerSince this having a separatelistserializer is so common, the above can be avoided by using
theserializer_list_classclass attribute provided byFormSchemaViewSetMixin.SerializerThe majority of the customization will occur inside serializer classes;
a real world example will often require customcreate,update,to_representation, etc methods.At the class level the serializer defines the form name:ChoiceSerializer -> Choice
QuestionAndChoiceSerializer -> Question And Choice
Choice -> ChoiceIf a different title is required (or no title for nested forms), then the__init__method can be updated:def__init__(self,*args,**kwargs):kwargs['label']='New Form Title'super().__init__(*args,**kwargs)Serializer Field AttributesThe following is a list of parameters that can be added to individual fields which modifiesreact-jsonschema-formfunctionality on the front-end.LabelUpdates the form input title text. Can also be used to provide translations.choice_text=serializers.CharField(label='What is the choice label?')The label can also be disabled completely viastyle:choice_text=serializers.CharField(style={'ui:options':{'label':False}})Note: This does not work forlistactions.Read OnlySettingread_only=Trueforces the encoder to skip it when building the form,
but still means the value gets sent in theformData:choice_text=serializers.CharField(read_only=True)This is useful for custom widgets which rely on data not related to the form (e.g.id).RequiredSettingrequired=Falseremoves frontend validation of the field:choice_text=serializers.CharField(required=False)Note: This has no effect onlistactions.Allow NullSettingallow_null=Trueallowsnullvalues to be sent back informData:choice_text=serializers.CharField(allow_null=True)Note: This has no effect onlistactions.DefaultBy setting a default value, a field is automatically set torequired=False.
TheformDataobject will also contain thedefaultvalue if it is not provided one.choice_text=serializers.CharField(default='example text')Note: This has no effect onlistactions.Validation MappingBuilt-in validators are automatically added to the schema. For instance:char_text=serializers.CharField(min_length=5,max_length=10)Will result in the following schema portion:{"type":"string","title":"Char text","maxLength":10,"minLength":5}The following core validators have mapping to json schema (https://ajv.js.org/json-schema.html):MaxLengthValidator: maxLengthMinLengthValidator: minLengthMaxValueValidator: maximumMinValueValidator: minimumRegexValidator: patternCustom validators can not be mapped directly to Ajv schema properies so they are rather provided in the json ui schema as hints.classMinSizeImageValidator:message=_('Image is too small, must be 1KB minimum.')code='image_min_1KB'def__call__(self,value):min_size=1024# 1KBifvalue.size<min_size:raiseserializers.ValidationError(self.message,code=self.code)image_field=serializers.ImageField(required=True,validators=[MinSizeImageValidator])Will result in the following ui schema portion:{"ui:widget":"file","ui:custom-validators":[{"code":"image_min_1KB","message":"Image is too small, must be 1KB minimum."}]}StyleThe DRFstyleparameter is adictand is therefore used for a number of different parameters.
There are anumber of optionsthatreact-jsonschema-formprovides, many of which should work out-of-the-box,
although not all options will have been tested.Since style params are appliedlast, they can overwrite other keys. Additionally, any key not
starting withschema:will be sent in thejsonpayload, so this can be a good place to send
additional attributes for custom widgets.The following are a list of valid (tested) keys and their uses.Note: This can also be done at the serializer level:def__init__(self,*args,**kwargs):kwargs['style']={'ui:template':'Card'}super().__init__(*args,**kwargs)Dependenciesreact-jsonschema-formallows for the use ofdependenciesbetween multiple fields. This library has analogues for the four types (bidirectional, unidirectional, conditional, and
dynamic).# Unidirectionalchoice_text=serializers.CharField(style={'schema:dependencies:simple':['votes']})# Bidirectional - note the different value styles, either is fine.choice_text=serializers.CharField(style={'schema:dependencies:simple':['votes']})votes=serializers.IntegerField(default=0,style={'schema:dependencies:simple':'choice_text'})# Conditionalchoice_text=serializers.CharField(style={'schema:dependencies:conditional':['votes']})# Dynamic - must be an enum field, and only one choice per dependency,# multiple choices can have the same dependencies (side-stepping this issue).choice_text=serializers.ChoiceField(choices=(('yes','Yes'),('no','No')),style={'schema:dependencies:dynamic':{'yes':['votes'],'no':None}})Field OverridesSince this framework doesn't cover 100% of the features of thereact-jsonschema-form, it is possible to providedictobjects which override the individual field properties:choice_text=serializers.CharField(style={'schema:override':{'type':'string','title':'Overridden title'},'uiSchema:override':{'ui:widget':'updown'},'column:override':{'title':'Overridden title','dataIndex':'question_text','key':'question_text',},'schema:dependencies:override':['votes']})Note: There is no validation around these overrides, so it is left up to the developer to ensure the resulting
schema is valid. For example,'schema:dependencies:override'will not remove fields from the main'properties'or'required'objects. (This can be done by omitting the dependant field from the serializer or usingread_only=True).List Sort OrderSends thedefaultSortOrderkey with thelistaction serializer:choice_text=serializers.CharField(,style={'schema:sort':'ascend'})Widget, Type, and EnumWhile the framework tries to provide sensible defaults for DRF fields,
sometimes custom frontend widgets need to provide custom behaviour.choice_text=serializers.CharField(style={'ui:widget':'textarea','schema:type':'string','schema:enum':'choices'})More information can be found ontypesandenum.enumcan also be set to thestringchoices(as in the example),
to try and use thefield.choicesattribute.PlaceholderThe HTML placeholder text can be updated in the following way:choice_text=serializers.CharField(style={'ui:placeholder':'This a placeholder value'})Text Area Widget RowsWhen theui:widgetis set totextarea(see above), therowscan be set via:choice_text=serializers.CharField(style={'ui:widget':'textarea','ui:options':{'rows':8},})DisabledAn input field can bedisabledin the following way:choice_text=serializers.CharField(style={'ui:disabled':'true'})SettingsDRF_REACT_TEMPLATE_TYPE_MAPAllows for custom fields to be added toProcessingMixin.TYPE_MAPin this way:DRF_REACT_TEMPLATE_TYPE_MAP={'ImageField':{'type':'image','widget':'file'},}The default supported field types are:{'CharField':{'type':'string'},'IntegerField':{'type':'integer','widget':'updown'},'FloatField':{'type':'number','widget':'updown'},'DecimalField':{'type':'number','widget':'updown'},'BooleanField':{'type':'boolean'},'DateTimeField':{'type':'string','widget':'date-time'},'DateField':{'type':'string','widget':'date'},'URLField':{'type':'string','widget':'uri'},'ChoiceField':{'type':'string','enum':'choices'},'EmailField':{'type':'string','widget':'email'},'ListField':{'type':'array'},}DevelopmentThis Repo usesPoetry,
and setup for development is as simple as follows:poetryinit
pre-commitinstall