sim3x вот велосипед-та здесь нужен :) Так как DRF и его TemplateHTMLRenderer рендерить уже готовую форму которую я не смогу использовать с AngularJS Material. На данный момент я сделал миксин для формы в Django:
class MDSwitchRenderer(RadioFieldRenderer):
def render(self):
return render_to_string('switch_widget.html', {'field': self})
class MDSwitch(RadioSelect):
renderer = MDSwitchRenderer
class MDSelect(Widget):
allow_multiple_selected = False
def __init__(self, attrs=None, choices=()):
super(MDSelect, self).__init__(attrs)
self.choices = list(choices)
def render(self, name, value, attrs=None, choices=()):
if value is None:
value = ''
final_attrs = self.build_attrs(attrs, name=name)
output = [format_html('<md-select{}>', flatatt(final_attrs))]
options = self.render_options(choices, [value])
if options:
output.append(options)
output.append('</md-select>')
return mark_safe('\n'.join(output))
def render_option(self, selected_choices, option_value, option_label):
if option_value is None:
option_value = ''
option_value = force_text(option_value)
if option_value in selected_choices:
selected_html = mark_safe(' selected')
if not self.allow_multiple_selected:
selected_choices.remove(option_value)
else:
selected_html = ''
return format_html('<md-option data-ng-value="{}"{}>{}</md-option>', option_value, selected_html, force_text(option_label))
def render_options(self, choices, selected_choices):
selected_choices = set(force_text(v) for v in selected_choices)
output = []
for option_value, option_label in chain(self.choices, choices):
if isinstance(option_label, (list, tuple)):
output.append(format_html('<md-optgroup label="{}">', force_text(option_value)))
for option in option_label:
output.append(self.render_option(selected_choices, *option))
output.append('</md-optgroup>')
else:
output.append(self.render_option(selected_choices, option_value, option_label))
return '\n'.join(output)
class MDSelectMultiple(MDSelect):
allow_multiple_selected = True
def render(self, name, value, attrs=None, choices=()):
if value is None:
value = []
final_attrs = self.build_attrs(attrs, name=name)
output = [format_html('<md-select multiple="multiple"{}>', flatatt(final_attrs))]
options = self.render_options(choices, value)
if options:
output.append(options)
output.append('</md-select>')
return mark_safe('\n'.join(output))
def value_from_datadict(self, data, files, name):
if isinstance(data, MultiValueDict):
return data.getlist(name)
return data.get(name)
class MDFormMixin(object):
"""
Angular Material Design form mixin
"""
def __init__(self, *args, **kwargs):
super(MDFormMixin, self).__init__(args, kwargs)
for field_name in self.fields:
field = self.fields.get(field_name)
if field:
if type(field) in (ModelChoiceField, ):
field.empty_label = None
field.widget = MDSelect(choices=field.choices)
elif type(field) in (ModelMultipleChoiceField, ):
field.empty_label = None
field.widget = MDSelectMultiple(choices=field.choices)
if type(field.widget) in (TextInput, Textarea):
field.widget.attrs.update({'md-maxlength': field.max_length, })
#elif type(field.widget) in (TimeInput, ): # FIXME: Remove
# field.widget.input_type = 'time'
# field.widget.attrs.update({'step': 1, })
elif type(field.widget) in (Select, ):
field.widget = MDSelect(choices=field.choices)
if field.required:
field.widget.attrs.update({'required': 'required'})
field.widget.attrs.update({'ng-model': 'vm.object.'+field_name})
template "switch_widget.html":
<md-radio-group ng-model="vm.object.{{ field.name }}">
{% for choice in field %}
<md-radio-button ng-value="{{ choice.choice_value|lower }}">
{{ choice.choice_label }}
</md-radio-button>
{% endfor %}
</md-radio-group>
и template самой формы "django_form.html":
{% if form.fieldsets %}
<md-content>
{% for fieldset in form.fieldsets %}
<div{% if fieldset.class %} class="{{ fieldset.classes }}"{% endif %}{% if fieldset.description %} layout="{{ fieldset.description }}{% endif %}">
{% for field in fieldset %}
<md-input-container class="md-block" flex>
<label>{{ field.label }}</label>
{{ field }}
{% if field.help_text %}
<div class="hint">{{ field.help_text }}</div>
{% endif %}
<div ng-messages="vm.objectForm.{{ field.name }}.$error">
<div ng-message="required" ng-show="vm.objectForm.{{ field.name }}.$error['required']">Обязательное поле для заполнения!</div>
<div ng-message="md-maxlength" ng-show="vm.objectForm.{{ field.name }}.$error['md-maxlength']">Длина строки не должна превышать {{ field.field.max_length }} символов.</div>
</div>
</md-input-container>
{% endfor %}
</div>
{% endfor %}
</md-content>
{% endif %}
Это связка работает. Но у меня возникла проблема когда я начал использовать в Angular ControllerAs :( Когда использовал $scope таких проблем не было :)