2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-04-28 03:26:45 +00:00

refactor(backend): metadata endpoint (#9488)

* refactor(backend): simplify metadata endpoint

* fix imports

* simplify even more

* remove unneeded schema tooling

* fix attr handling
This commit is contained in:
Matthias Mair 2025-04-10 01:09:52 +02:00 committed by GitHub
parent 4ea8f68819
commit dc1acfdacb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 54 additions and 93 deletions

View File

@ -1,7 +1,6 @@
"""Main JSON interface views.""" """Main JSON interface views."""
import json import json
import sys
from pathlib import Path from pathlib import Path
from django.conf import settings from django.conf import settings
@ -18,15 +17,14 @@ from rest_framework.response import Response
from rest_framework.serializers import ValidationError from rest_framework.serializers import ValidationError
from rest_framework.views import APIView from rest_framework.views import APIView
import common.models import InvenTree.ready
import InvenTree.version import InvenTree.version
import users.models import users.models
from common.settings import get_global_setting from common.settings import get_global_setting
from InvenTree import helpers, ready from InvenTree import helpers
from InvenTree.auth_overrides import registration_enabled from InvenTree.auth_overrides import registration_enabled
from InvenTree.mixins import ListCreateAPI from InvenTree.mixins import ListCreateAPI
from InvenTree.sso import sso_registration_enabled from InvenTree.sso import sso_registration_enabled
from part.models import Part
from plugin.serializers import MetadataSerializer from plugin.serializers import MetadataSerializer
from users.models import ApiToken from users.models import ApiToken
@ -707,37 +705,32 @@ class APISearchView(GenericAPIView):
class MetadataView(RetrieveUpdateAPI): class MetadataView(RetrieveUpdateAPI):
"""Generic API endpoint for reading and editing metadata for a model.""" """Generic API endpoint for reading and editing metadata for a model."""
MODEL_REF = 'model' model = None # Placeholder for the model class
def get_model_type(self):
"""Return the model type associated with this API instance."""
model = self.kwargs.get(self.MODEL_REF, None)
if ready.isGeneratingSchema():
model = common.models.ProjectCode
if 'lookup_field' in self.kwargs:
# Set custom lookup field (instead of default 'pk' value) if supplied
self.lookup_field = self.kwargs.pop('lookup_field')
@classmethod
def as_view(cls, model, lookup_field=None, **initkwargs):
"""Override to ensure model specific rendering."""
if model is None: if model is None:
raise ValidationError( raise ValidationError(
f"MetadataView called without '{self.MODEL_REF}' parameter" "MetadataView defined without 'model' arg"
) # pragma: no cover ) # pragma: no cover
initkwargs['model'] = model
return model # Set custom lookup field (instead of default 'pk' value) if supplied
if lookup_field:
initkwargs['lookup_field'] = lookup_field
return super().as_view(**initkwargs)
def get_permission_model(self): def get_permission_model(self):
"""Return the 'permission' model associated with this view.""" """Return the 'permission' model associated with this view."""
return self.get_model_type() return self.model
def get_queryset(self): def get_queryset(self):
"""Return the queryset for this endpoint.""" """Return the queryset for this endpoint."""
return self.get_model_type().objects.all() return self.model.objects.all()
def get_serializer(self, *args, **kwargs): def get_serializer(self, *args, **kwargs):
"""Return MetadataSerializer instance.""" """Return MetadataSerializer instance."""
# Detect if we are currently generating the OpenAPI schema # Detect if we are currently generating the OpenAPI schema
if 'spectacular' in sys.argv: return MetadataSerializer(self.model, *args, **kwargs)
return MetadataSerializer(Part, *args, **kwargs) # pragma: no cover
return MetadataSerializer(self.get_model_type(), *args, **kwargs)

View File

@ -920,8 +920,7 @@ build_api_urls = [
include([ include([
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=BuildItem),
{'model': BuildItem},
name='api-build-item-metadata', name='api-build-item-metadata',
), ),
path('', BuildItemDetail.as_view(), name='api-build-item-detail'), path('', BuildItemDetail.as_view(), name='api-build-item-detail'),
@ -967,8 +966,7 @@ build_api_urls = [
path('unallocate/', BuildUnallocate.as_view(), name='api-build-unallocate'), path('unallocate/', BuildUnallocate.as_view(), name='api-build-unallocate'),
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=Build),
{'model': Build},
name='api-build-metadata', name='api-build-metadata',
), ),
path('', BuildDetail.as_view(), name='api-build-detail'), path('', BuildDetail.as_view(), name='api-build-detail'),

View File

@ -986,8 +986,7 @@ common_api_urls = [
include([ include([
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=common.models.Attachment),
{'model': common.models.Attachment},
name='api-attachment-metadata', name='api-attachment-metadata',
), ),
path('', AttachmentDetail.as_view(), name='api-attachment-detail'), path('', AttachmentDetail.as_view(), name='api-attachment-detail'),
@ -1012,8 +1011,7 @@ common_api_urls = [
include([ include([
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=common.models.ProjectCode),
{'model': common.models.ProjectCode},
name='api-project-code-metadata', name='api-project-code-metadata',
), ),
path( path(

View File

@ -516,8 +516,7 @@ manufacturer_part_api_urls = [
include([ include([
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=ManufacturerPart),
{'model': ManufacturerPart},
name='api-manufacturer-part-metadata', name='api-manufacturer-part-metadata',
), ),
path( path(
@ -538,8 +537,7 @@ supplier_part_api_urls = [
include([ include([
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=SupplierPart),
{'model': SupplierPart},
name='api-supplier-part-metadata', name='api-supplier-part-metadata',
), ),
path('', SupplierPartDetail.as_view(), name='api-supplier-part-detail'), path('', SupplierPartDetail.as_view(), name='api-supplier-part-detail'),
@ -574,8 +572,7 @@ company_api_urls = [
include([ include([
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=Company),
{'model': Company},
name='api-company-metadata', name='api-company-metadata',
), ),
path('', CompanyDetail.as_view(), name='api-company-detail'), path('', CompanyDetail.as_view(), name='api-company-detail'),
@ -589,8 +586,7 @@ company_api_urls = [
include([ include([
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=Contact),
{'model': Contact},
name='api-contact-metadata', name='api-contact-metadata',
), ),
path('', ContactDetail.as_view(), name='api-contact-detail'), path('', ContactDetail.as_view(), name='api-contact-detail'),

View File

@ -1779,8 +1779,7 @@ order_api_urls = [
path('issue/', PurchaseOrderIssue.as_view(), name='api-po-issue'), path('issue/', PurchaseOrderIssue.as_view(), name='api-po-issue'),
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=models.PurchaseOrder),
{'model': models.PurchaseOrder},
name='api-po-metadata', name='api-po-metadata',
), ),
path( path(
@ -1812,8 +1811,7 @@ order_api_urls = [
include([ include([
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=models.PurchaseOrderLineItem),
{'model': models.PurchaseOrderLineItem},
name='api-po-line-metadata', name='api-po-line-metadata',
), ),
path( path(
@ -1835,8 +1833,7 @@ order_api_urls = [
include([ include([
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=models.PurchaseOrderExtraLine),
{'model': models.PurchaseOrderExtraLine},
name='api-po-extra-line-metadata', name='api-po-extra-line-metadata',
), ),
path( path(
@ -1868,8 +1865,7 @@ order_api_urls = [
), ),
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=models.SalesOrderShipment),
{'model': models.SalesOrderShipment},
name='api-so-shipment-metadata', name='api-so-shipment-metadata',
), ),
path( path(
@ -1910,8 +1906,7 @@ order_api_urls = [
), ),
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=models.SalesOrder),
{'model': models.SalesOrder},
name='api-so-metadata', name='api-so-metadata',
), ),
# SalesOrder detail endpoint # SalesOrder detail endpoint
@ -1938,8 +1933,7 @@ order_api_urls = [
include([ include([
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=models.SalesOrderLineItem),
{'model': models.SalesOrderLineItem},
name='api-so-line-metadata', name='api-so-line-metadata',
), ),
path( path(
@ -1961,8 +1955,7 @@ order_api_urls = [
include([ include([
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=models.SalesOrderExtraLine),
{'model': models.SalesOrderExtraLine},
name='api-so-extra-line-metadata', name='api-so-extra-line-metadata',
), ),
path( path(
@ -2018,8 +2011,7 @@ order_api_urls = [
), ),
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=models.ReturnOrder),
{'model': models.ReturnOrder},
name='api-return-order-metadata', name='api-return-order-metadata',
), ),
path( path(
@ -2047,8 +2039,7 @@ order_api_urls = [
include([ include([
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=models.ReturnOrderLineItem),
{'model': models.ReturnOrderLineItem},
name='api-return-order-line-metadata', name='api-return-order-line-metadata',
), ),
path( path(
@ -2079,8 +2070,7 @@ order_api_urls = [
include([ include([
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=models.ReturnOrderExtraLine),
{'model': models.ReturnOrderExtraLine},
name='api-return-order-extra-line-metadata', name='api-return-order-extra-line-metadata',
), ),
path( path(

View File

@ -1996,8 +1996,9 @@ part_api_urls = [
include([ include([
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(
{'model': PartCategoryParameterTemplate}, model=PartCategoryParameterTemplate
),
name='api-part-category-parameter-metadata', name='api-part-category-parameter-metadata',
), ),
path( path(
@ -2020,8 +2021,7 @@ part_api_urls = [
include([ include([
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=PartCategory),
{'model': PartCategory},
name='api-part-category-metadata', name='api-part-category-metadata',
), ),
# PartCategory detail endpoint # PartCategory detail endpoint
@ -2040,8 +2040,7 @@ part_api_urls = [
include([ include([
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=PartTestTemplate),
{'model': PartTestTemplate},
name='api-part-test-template-metadata', name='api-part-test-template-metadata',
), ),
path( path(
@ -2091,8 +2090,7 @@ part_api_urls = [
include([ include([
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=PartRelated),
{'model': PartRelated},
name='api-part-related-metadata', name='api-part-related-metadata',
), ),
path( path(
@ -2115,8 +2113,7 @@ part_api_urls = [
include([ include([
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=PartParameterTemplate),
{'model': PartParameterTemplate},
name='api-part-parameter-template-metadata', name='api-part-parameter-template-metadata',
), ),
path( path(
@ -2138,8 +2135,7 @@ part_api_urls = [
include([ include([
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=PartParameter),
{'model': PartParameter},
name='api-part-parameter-metadata', name='api-part-parameter-metadata',
), ),
path( path(
@ -2217,10 +2213,7 @@ part_api_urls = [
), ),
# Part metadata # Part metadata
path( path(
'metadata/', 'metadata/', MetadataView.as_view(model=Part), name='api-part-metadata'
MetadataView.as_view(),
{'model': Part},
name='api-part-metadata',
), ),
# Part pricing # Part pricing
path('pricing/', PartPricingDetail.as_view(), name='api-part-pricing'), path('pricing/', PartPricingDetail.as_view(), name='api-part-pricing'),
@ -2241,8 +2234,7 @@ bom_api_urls = [
include([ include([
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=BomItemSubstitute),
{'model': BomItemSubstitute},
name='api-bom-substitute-metadata', name='api-bom-substitute-metadata',
), ),
path( path(
@ -2263,8 +2255,7 @@ bom_api_urls = [
path('validate/', BomItemValidate.as_view(), name='api-bom-item-validate'), path('validate/', BomItemValidate.as_view(), name='api-bom-item-validate'),
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=BomItem),
{'model': BomItem},
name='api-bom-item-metadata', name='api-bom-item-metadata',
), ),
path('', BomDetail.as_view(), name='api-bom-item-detail'), path('', BomDetail.as_view(), name='api-bom-item-detail'),

View File

@ -502,8 +502,9 @@ plugin_api_urls = [
), ),
path( path(
'metadata/', 'metadata/',
PluginMetadataView.as_view(), PluginMetadataView.as_view(
{'model': PluginConfig, 'lookup_field': 'key'}, model=PluginConfig, lookup_field='key'
),
name='api-plugin-metadata', name='api-plugin-metadata',
), ),
path( path(

View File

@ -362,8 +362,7 @@ label_api_urls = [
include([ include([
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=report.models.LabelTemplate),
{'model': report.models.LabelTemplate},
name='api-label-template-metadata', name='api-label-template-metadata',
), ),
path( path(
@ -390,8 +389,7 @@ report_api_urls = [
include([ include([
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=report.models.ReportTemplate),
{'model': report.models.ReportTemplate},
name='api-report-template-metadata', name='api-report-template-metadata',
), ),
path( path(

View File

@ -1511,8 +1511,7 @@ stock_api_urls = [
include([ include([
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=StockLocation),
{'model': StockLocation},
name='api-location-metadata', name='api-location-metadata',
), ),
path('', StockLocationDetail.as_view(), name='api-location-detail'), path('', StockLocationDetail.as_view(), name='api-location-detail'),
@ -1530,8 +1529,7 @@ stock_api_urls = [
include([ include([
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=StockLocationType),
{'model': StockLocationType},
name='api-location-type-metadata', name='api-location-type-metadata',
), ),
path( path(
@ -1561,8 +1559,7 @@ stock_api_urls = [
include([ include([
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=StockItemTestResult),
{'model': StockItemTestResult},
name='api-stock-test-result-metadata', name='api-stock-test-result-metadata',
), ),
path( path(
@ -1604,8 +1601,7 @@ stock_api_urls = [
path('install/', StockItemInstall.as_view(), name='api-stock-item-install'), path('install/', StockItemInstall.as_view(), name='api-stock-item-install'),
path( path(
'metadata/', 'metadata/',
MetadataView.as_view(), MetadataView.as_view(model=StockItem),
{'model': StockItem},
name='api-stock-item-metadata', name='api-stock-item-metadata',
), ),
path('return/', StockItemReturn.as_view(), name='api-stock-item-return'), path('return/', StockItemReturn.as_view(), name='api-stock-item-return'),