Задать вопрос

Как конвертировать модель Django в Json Schema?

Здравствуйте!
Сильно не пинайте нужен дельный совет.
Разрабатывается один проект в бекэнде Django + Django Rest Framework а в фронтэнде AngularJS. Сложилась такая ситуация что надо генерировать форму модели Django в Angular. Хотелось бы использовать для этого Json Schema. Народ дайте совет как конвертировать модель Django в Json Schema? Или в какую сторону копать чтоб конвертировать Django модель в форму?

Заранее огромное спасибо!!!
  • Вопрос задан
  • 1520 просмотров
Подписаться 6 Оценить Комментировать
Пригласить эксперта
Ответы на вопрос 5
sim3x
@sim3x
stackoverflow.com/questions/18561585/django-form-t...

пакет староват, но для примера сойдет
https://github.com/WiserTogether/django-remote-forms

но лучше не изобретать велосипед и www.django-rest-framework.org/topics/html-and-form...
Ответ написан
Комментировать
chupasaurus
@chupasaurus
Сею рефлекторное, злое, временное
Сериализация в Django и особенности json
Схема не очень подходит для определения динамических структур.
Ответ написан
Комментировать
Решений для автоматического получения схемы из модели я не знаю, и не уверен что существуют. Если решите руками описывать то рекомендую https://jsl.readthedocs.org/en/latest/
Ответ написан
Khikmat
@Khikmat Автор вопроса
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 таких проблем не было :)
Ответ написан
Комментировать
@SlimHouse
Сквозь тернии к звездам
Для DRF есть генератор документации: rest_framework_swagger. В нем есть похожий функционал. Можете попробовать посмотреть, тем более у вас как раз DRF используется.
В классе DocumentationGenerator метод get_models https://github.com/marcgibbons/django-rest-swagger...
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы