diff --git a/InvenTree/InvenTree/metadata.py b/InvenTree/InvenTree/metadata.py index b344053db0..5ca87b9eee 100644 --- a/InvenTree/InvenTree/metadata.py +++ b/InvenTree/InvenTree/metadata.py @@ -1,24 +1,18 @@ - # -*- coding: utf-8 -*- + from __future__ import unicode_literals -from django.db import models - -from collections import OrderedDict - -from django.core.exceptions import PermissionDenied -from django.http import Http404 -from django.utils.encoding import force_str - -from rest_framework import exceptions, serializers, fields -from rest_framework.request import clone_request -from rest_framework.utils.field_mapping import ClassLookupDict +import logging +from rest_framework import serializers from rest_framework.metadata import SimpleMetadata import users.models +logger = logging.getLogger('inventree') + + class InvenTreeMetadata(SimpleMetadata): """ Custom metadata class for the DRF API. @@ -88,3 +82,31 @@ class InvenTreeMetadata(SimpleMetadata): pass return metadata + + def get_field_info(self, field): + """ + Given an instance of a serializer field, return a dictionary + of metadata about it. + + We take the regular DRF metadata and add our own unique flavor + """ + + # Run super method first + field_info = super().get_field_info(field) + + # Introspect writable related fields + if field_info['type'] == 'field' and not field_info['read_only']: + + # If the field is a PrimaryKeyRelatedField, we can extract the model from the queryset + if isinstance(field, serializers.PrimaryKeyRelatedField): + model = field.queryset.model + else: + logger.debug("Could not extract model for:", field_info['label'], '->', field) + model = None + + if model: + # Mark this field as "related", and point to the URL where we can get the data! + field_info['type'] = 'related field' + field_info['api_url'] = model.get_api_url() + + return field_info diff --git a/InvenTree/templates/js/forms.js b/InvenTree/templates/js/forms.js index ffc7dc8de8..64a062c752 100644 --- a/InvenTree/templates/js/forms.js +++ b/InvenTree/templates/js/forms.js @@ -213,6 +213,8 @@ function constructFormBody(url, fields, options={}) { } } + // Render selected fields + for (var idx = 0; idx < field_names.length; idx++) { var name = field_names[idx]; @@ -242,6 +244,7 @@ function constructFormBody(url, fields, options={}) { modalSetTitle(modal, title); + // Insert generated form content $(modal).find('.modal-form-content').html(html); $(modal).modal('show'); @@ -434,8 +437,8 @@ function constructInput(name, parameters, options={}) { case 'choice': func = constructChoiceInput; break; - case 'field': - // TODO: foreign key field! + case 'related field': + func = constructRelatedFieldInput; break; default: // Unsupported field type! @@ -597,6 +600,22 @@ function constructChoiceInput(name, parameters, options={}) { } +/* + * Construct a "related field" input. + * This will create a "select" input which will then, (after form is loaded), + * be converted into a select2 input. + * This will then be served custom data from the API (as required)... + */ +function constructRelatedFieldInput(name, parameters, options={}) { + + var html = ``; + + // Don't load any options - they will be filled via an AJAX request + + return html; +} + + /* * Construct a 'help text' div based on the field parameters *