2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-10-24 09:57:40 +00:00

move filtering of serializer fields out of functions into mixin

This commit is contained in:
Matthias Mair
2025-10-05 18:47:25 +02:00
parent 2e7e8d5eee
commit 3ee3cea8d8
5 changed files with 229 additions and 304 deletions

View File

@@ -28,6 +28,52 @@ from common.currency import currency_code_default, currency_code_mappings
from InvenTree.fields import InvenTreeRestURLField, InvenTreeURLField
# region path filtering
class OptionalFilterabelSerializer(serializers.Serializer):
"""Mixin to add context to serializer."""
is_filterable = None
is_filterable_default = None
def __init__(self, *args, **kwargs):
"""Initialize the serializer."""
self.is_filterable = kwargs.pop('is_filterable', None)
self.is_filterable_default = kwargs.pop('is_filterable_default', True)
super().__init__(*args, **kwargs)
class PathScopedMixin:
"""Mixin to disable a serializer field based on kwargs passed to the view."""
def __init__(self, *args, **kwargs):
"""Initialization routine for the serializer."""
flt_fld = {
k: a for k, a in self.fields.items() if getattr(a, 'is_filterable', None)
}
filter_targets = {k: kwargs.pop(k, False) for k in flt_fld}
super().__init__(*args, **kwargs)
if InvenTree.ready.isGeneratingSchema():
return
# Throw out fields which are not requested
for k, v in filter_targets.items():
if v is not True:
self.fields.pop(k, None)
# Decorator for marking serialzier fields that can be filtered out
def can_filter(func, default=False):
"""Decorator for marking serializer fields as filterable."""
func._kwargs['is_filterable'] = True
func._kwargs['is_filterable_default'] = default
return func
# endregion
class EmptySerializer(serializers.Serializer):
"""Empty serializer for use in testing."""
@@ -222,7 +268,9 @@ class DependentField(serializers.Field):
return None
class InvenTreeModelSerializer(serializers.ModelSerializer):
class InvenTreeModelSerializer(
OptionalFilterabelSerializer, serializers.ModelSerializer
):
"""Inherits the standard Django ModelSerializer class, but also ensures that the underlying model class data are checked on validation."""
# Switch out URLField mapping

View File

@@ -52,6 +52,8 @@ from InvenTree.serializers import (
InvenTreeModelSerializer,
InvenTreeMoneySerializer,
NotesFieldMixin,
PathScopedMixin,
can_filter,
)
from order.status_codes import (
PurchaseOrderStatusGroups,
@@ -276,15 +278,6 @@ class AbstractExtraLineSerializer(
):
"""Abstract Serializer for a ExtraLine object."""
def __init__(self, *args, **kwargs):
"""Initialization routine for the serializer."""
order_detail = kwargs.pop('order_detail', False)
super().__init__(*args, **kwargs)
if order_detail is not True and not isGeneratingSchema():
self.fields.pop('order_detail', None)
quantity = serializers.FloatField()
price = InvenTreeMoneySerializer(allow_null=True)
@@ -343,15 +336,6 @@ class PurchaseOrderSerializer(
'order_currency': {'required': False},
}
def __init__(self, *args, **kwargs):
"""Initialization routine for the serializer."""
supplier_detail = kwargs.pop('supplier_detail', False)
super().__init__(*args, **kwargs)
if supplier_detail is not True and not isGeneratingSchema():
self.fields.pop('supplier_detail', None)
def skip_create_fields(self):
"""Skip these fields when instantiating a new object."""
fields = super().skip_create_fields()
@@ -389,8 +373,10 @@ class PurchaseOrderSerializer(
source='supplier.name', read_only=True, label=_('Supplier Name')
)
supplier_detail = CompanyBriefSerializer(
source='supplier', many=False, read_only=True, allow_null=True
supplier_detail = can_filter(
CompanyBriefSerializer(
source='supplier', many=False, read_only=True, allow_null=True
)
)
@@ -522,20 +508,17 @@ class PurchaseOrderLineItemSerializer(
def __init__(self, *args, **kwargs):
"""Initialization routine for the serializer."""
part_detail = kwargs.pop('part_detail', False)
order_detail = kwargs.pop('order_detail', False)
super().__init__(*args, **kwargs)
if isGeneratingSchema():
return
# TODO INVE-T1 support complex filters
if part_detail is not True:
self.fields.pop('part_detail', None)
self.fields.pop('supplier_part_detail', None)
if order_detail is not True:
self.fields.pop('order_detail', None)
def skip_create_fields(self):
"""Return a list of fields to skip when creating a new object."""
return ['auto_pricing', 'merge_items', *super().skip_create_fields()]
@@ -644,8 +627,10 @@ class PurchaseOrderLineItemSerializer(
help_text=_('Purchase price currency')
)
order_detail = PurchaseOrderSerializer(
source='order', read_only=True, allow_null=True, many=False
order_detail = can_filter(
PurchaseOrderSerializer(
source='order', read_only=True, allow_null=True, many=False
)
)
build_order_detail = build.serializers.BuildSerializer(
@@ -724,8 +709,10 @@ class PurchaseOrderExtraLineSerializer(
):
"""Serializer for a PurchaseOrderExtraLine object."""
order_detail = PurchaseOrderSerializer(
source='order', many=False, read_only=True, allow_null=True
order_detail = can_filter(
PurchaseOrderSerializer(
source='order', many=False, read_only=True, allow_null=True
)
)
class Meta(AbstractExtraLineMeta):
@@ -1009,15 +996,6 @@ class SalesOrderSerializer(
extra_kwargs = {'order_currency': {'required': False}}
def __init__(self, *args, **kwargs):
"""Initialization routine for the serializer."""
customer_detail = kwargs.pop('customer_detail', False)
super().__init__(*args, **kwargs)
if customer_detail is not True and not isGeneratingSchema():
self.fields.pop('customer_detail', None)
def skip_create_fields(self):
"""Skip these fields when instantiating a new object."""
fields = super().skip_create_fields()
@@ -1058,8 +1036,10 @@ class SalesOrderSerializer(
return queryset
customer_detail = CompanyBriefSerializer(
source='customer', many=False, read_only=True, allow_null=True
customer_detail = can_filter(
CompanyBriefSerializer(
source='customer', many=False, read_only=True, allow_null=True
)
)
shipments_count = serializers.IntegerField(
@@ -1083,6 +1063,7 @@ class SalesOrderIssueSerializer(OrderAdjustSerializer):
class SalesOrderLineItemSerializer(
DataImportExportSerializerMixin,
AbstractLineItemSerializer,
PathScopedMixin,
InvenTreeModelSerializer,
):
"""Serializer for a SalesOrderLineItem object."""
@@ -1116,29 +1097,6 @@ class SalesOrderLineItemSerializer(
'on_order',
]
def __init__(self, *args, **kwargs):
"""Initialization routine for the serializer.
- Add extra related serializer information if required
"""
part_detail = kwargs.pop('part_detail', False)
order_detail = kwargs.pop('order_detail', False)
customer_detail = kwargs.pop('customer_detail', False)
super().__init__(*args, **kwargs)
if isGeneratingSchema():
return
if part_detail is not True:
self.fields.pop('part_detail', None)
if order_detail is not True:
self.fields.pop('order_detail', None)
if customer_detail is not True:
self.fields.pop('customer_detail', None)
@staticmethod
def annotate_queryset(queryset):
"""Add some extra annotations to this queryset.
@@ -1236,14 +1194,18 @@ class SalesOrderLineItemSerializer(
return queryset
order_detail = SalesOrderSerializer(
source='order', many=False, read_only=True, allow_null=True
order_detail = can_filter(
SalesOrderSerializer(
source='order', many=False, read_only=True, allow_null=True
)
)
part_detail = PartBriefSerializer(
source='part', many=False, read_only=True, allow_null=True
part_detail = can_filter(
PartBriefSerializer(source='part', many=False, read_only=True, allow_null=True)
)
customer_detail = CompanyBriefSerializer(
source='order.customer', many=False, read_only=True, allow_null=True
customer_detail = can_filter(
CompanyBriefSerializer(
source='order.customer', many=False, read_only=True, allow_null=True
)
)
# Annotated fields
@@ -1291,15 +1253,6 @@ class SalesOrderShipmentSerializer(NotesFieldMixin, InvenTreeModelSerializer):
'notes',
]
def __init__(self, *args, **kwargs):
"""Initialization routine for the serializer."""
order_detail = kwargs.pop('order_detail', True)
super().__init__(*args, **kwargs)
if not order_detail and not isGeneratingSchema():
self.fields.pop('order_detail', None)
@staticmethod
def annotate_queryset(queryset):
"""Annotate the queryset with extra information."""
@@ -1314,8 +1267,11 @@ class SalesOrderShipmentSerializer(NotesFieldMixin, InvenTreeModelSerializer):
read_only=True, allow_null=True, label=_('Allocated Items')
)
order_detail = SalesOrderSerializer(
source='order', read_only=True, allow_null=True, many=False
order_detail = can_filter(
SalesOrderSerializer(
source='order', read_only=True, allow_null=True, many=False
),
True,
)
@@ -1352,34 +1308,6 @@ class SalesOrderAllocationSerializer(InvenTreeModelSerializer):
read_only_fields = ['line', '']
def __init__(self, *args, **kwargs):
"""Initialization routine for the serializer."""
order_detail = kwargs.pop('order_detail', False)
part_detail = kwargs.pop('part_detail', True)
item_detail = kwargs.pop('item_detail', True)
location_detail = kwargs.pop('location_detail', False)
customer_detail = kwargs.pop('customer_detail', False)
super().__init__(*args, **kwargs)
if isGeneratingSchema():
return
if not order_detail:
self.fields.pop('order_detail', None)
if not part_detail:
self.fields.pop('part_detail', None)
if not item_detail:
self.fields.pop('item_detail', None)
if not location_detail:
self.fields.pop('location_detail', None)
if not customer_detail:
self.fields.pop('customer_detail', None)
part = serializers.PrimaryKeyRelatedField(source='item.part', read_only=True)
order = serializers.PrimaryKeyRelatedField(
source='line.order', many=False, read_only=True
@@ -1391,26 +1319,38 @@ class SalesOrderAllocationSerializer(InvenTreeModelSerializer):
)
# Extra detail fields
order_detail = SalesOrderSerializer(
source='line.order', many=False, read_only=True, allow_null=True
order_detail = can_filter(
SalesOrderSerializer(
source='line.order', many=False, read_only=True, allow_null=True
)
)
part_detail = PartBriefSerializer(
source='item.part', many=False, read_only=True, allow_null=True
part_detail = can_filter(
PartBriefSerializer(
source='item.part', many=False, read_only=True, allow_null=True
),
True,
)
item_detail = stock.serializers.StockItemSerializer(
source='item',
many=False,
read_only=True,
allow_null=True,
part_detail=False,
location_detail=False,
supplier_part_detail=False,
item_detail = can_filter(
stock.serializers.StockItemSerializer(
source='item',
many=False,
read_only=True,
allow_null=True,
part_detail=False,
location_detail=False,
supplier_part_detail=False,
),
True,
)
location_detail = stock.serializers.LocationBriefSerializer(
source='item.location', many=False, read_only=True, allow_null=True
location_detail = can_filter(
stock.serializers.LocationBriefSerializer(
source='item.location', many=False, read_only=True, allow_null=True
)
)
customer_detail = CompanyBriefSerializer(
source='line.order.customer', many=False, read_only=True, allow_null=True
customer_detail = can_filter(
CompanyBriefSerializer(
source='line.order.customer', many=False, read_only=True, allow_null=True
)
)
shipment_detail = SalesOrderShipmentSerializer(
@@ -1860,8 +1800,10 @@ class SalesOrderExtraLineSerializer(
model = order.models.SalesOrderExtraLine
order_detail = SalesOrderSerializer(
source='order', many=False, read_only=True, allow_null=True
order_detail = can_filter(
SalesOrderSerializer(
source='order', many=False, read_only=True, allow_null=True
)
)
@@ -1891,15 +1833,6 @@ class ReturnOrderSerializer(
read_only_fields = ['creation_date']
def __init__(self, *args, **kwargs):
"""Initialization routine for the serializer."""
customer_detail = kwargs.pop('customer_detail', False)
super().__init__(*args, **kwargs)
if customer_detail is not True and not isGeneratingSchema():
self.fields.pop('customer_detail', None)
def skip_create_fields(self):
"""Skip these fields when instantiating a new object."""
fields = super().skip_create_fields()
@@ -1929,8 +1862,10 @@ class ReturnOrderSerializer(
return queryset
customer_detail = CompanyBriefSerializer(
source='customer', many=False, read_only=True, allow_null=True
customer_detail = can_filter(
CompanyBriefSerializer(
source='customer', many=False, read_only=True, allow_null=True
)
)
@@ -2096,40 +2031,26 @@ class ReturnOrderLineItemSerializer(
'link',
]
def __init__(self, *args, **kwargs):
"""Initialization routine for the serializer."""
order_detail = kwargs.pop('order_detail', False)
item_detail = kwargs.pop('item_detail', False)
part_detail = kwargs.pop('part_detail', False)
super().__init__(*args, **kwargs)
if isGeneratingSchema():
return
if not order_detail:
self.fields.pop('order_detail', None)
if not item_detail:
self.fields.pop('item_detail', None)
if not part_detail:
self.fields.pop('part_detail', None)
order_detail = ReturnOrderSerializer(
source='order', many=False, read_only=True, allow_null=True
order_detail = can_filter(
ReturnOrderSerializer(
source='order', many=False, read_only=True, allow_null=True
)
)
quantity = serializers.FloatField(
label=_('Quantity'), help_text=_('Quantity to return')
)
item_detail = stock.serializers.StockItemSerializer(
source='item', many=False, read_only=True, allow_null=True
item_detail = can_filter(
stock.serializers.StockItemSerializer(
source='item', many=False, read_only=True, allow_null=True
)
)
part_detail = PartBriefSerializer(
source='item.part', many=False, read_only=True, allow_null=True
part_detail = can_filter(
PartBriefSerializer(
source='item.part', many=False, read_only=True, allow_null=True
)
)
price = InvenTreeMoneySerializer(allow_null=True)
@@ -2147,6 +2068,8 @@ class ReturnOrderExtraLineSerializer(
model = order.models.ReturnOrderExtraLine
order_detail = ReturnOrderSerializer(
source='order', many=False, read_only=True, allow_null=True
order_detail = can_filter(
ReturnOrderSerializer(
source='order', many=False, read_only=True, allow_null=True
)
)

View File

@@ -34,6 +34,7 @@ import users.models
from importer.registry import register_importer
from InvenTree.mixins import DataImportExportSerializerMixin
from InvenTree.ready import isGeneratingSchema
from InvenTree.serializers import can_filter
from users.serializers import UserSerializer
from .models import (
@@ -91,6 +92,7 @@ class CategorySerializer(
super().__init__(*args, **kwargs)
# TODO INVE-T1 support complex filters
if not path_detail and not isGeneratingSchema():
self.fields.pop('path', None)
@@ -355,6 +357,7 @@ class PartBriefSerializer(InvenTree.serializers.InvenTreeModelSerializer):
super().__init__(*args, **kwargs)
# TODO INVE-T1 support complex filters
if not pricing and not isGeneratingSchema():
self.fields.pop('pricing_min', None)
self.fields.pop('pricing_max', None)
@@ -414,25 +417,6 @@ class PartParameterSerializer(
read_only_fields = ['updated', 'updated_by']
def __init__(self, *args, **kwargs):
"""Custom initialization method for the serializer.
Allows us to optionally include or exclude particular information
"""
template_detail = kwargs.pop('template_detail', True)
part_detail = kwargs.pop('part_detail', False)
super().__init__(*args, **kwargs)
if isGeneratingSchema():
return
if not part_detail:
self.fields.pop('part_detail', None)
if not template_detail:
self.fields.pop('template_detail', None)
def save(self):
"""Save the PartParameter instance."""
instance = super().save()
@@ -444,12 +428,15 @@ class PartParameterSerializer(
return instance
part_detail = PartBriefSerializer(
source='part', many=False, read_only=True, allow_null=True
part_detail = can_filter(
PartBriefSerializer(source='part', many=False, read_only=True, allow_null=True)
)
template_detail = PartParameterTemplateSerializer(
source='template', many=False, read_only=True, allow_null=True
template_detail = can_filter(
PartParameterTemplateSerializer(
source='template', many=False, read_only=True, allow_null=True
),
True,
)
updated_by_detail = UserSerializer(
@@ -737,9 +724,7 @@ class PartSerializer(
- Allows us to optionally pass extra fields based on the query.
"""
self.starred_parts = kwargs.pop('starred_parts', [])
category_detail = kwargs.pop('category_detail', False)
location_detail = kwargs.pop('location_detail', False)
parameters = kwargs.pop('parameters', False)
create = kwargs.pop('create', False)
pricing = kwargs.pop('pricing', True)
path_detail = kwargs.pop('path_detail', False)
@@ -749,15 +734,11 @@ class PartSerializer(
if isGeneratingSchema():
return
if not category_detail:
self.fields.pop('category_detail', None)
# TODO INVE-T1 support complex filters
if not location_detail:
self.fields.pop('default_location_detail', None)
if not parameters:
self.fields.pop('parameters', None)
# TODO INVE-T1 support complex filters
if not path_detail:
self.fields.pop('category_path', None)
@@ -769,6 +750,7 @@ class PartSerializer(
continue
self.fields.pop(f, None)
# TODO INVE-T1 support complex filters
if not pricing:
self.fields.pop('pricing_min', None)
self.fields.pop('pricing_max', None)
@@ -888,8 +870,10 @@ class PartSerializer(
return part in self.starred_parts
# Extra detail for the category
category_detail = CategorySerializer(
source='category', many=False, read_only=True, allow_null=True
category_detail = can_filter(
CategorySerializer(
source='category', many=False, read_only=True, allow_null=True
)
)
category_path = serializers.ListField(
@@ -1018,7 +1002,9 @@ class PartSerializer(
source='pricing_data.updated', allow_null=True, read_only=True
)
parameters = PartParameterSerializer(many=True, read_only=True, allow_null=True)
parameters = can_filter(
PartParameterSerializer(many=True, read_only=True, allow_null=True)
)
# Extra fields used only for creation of a new Part instance
duplicate = DuplicatePartSerializer(
@@ -1649,29 +1635,14 @@ class BomItemSerializer(
- part_detail and sub_part_detail serializers are only included if requested.
- This saves a bunch of database requests
"""
can_build = kwargs.pop('can_build', True)
part_detail = kwargs.pop('part_detail', False)
sub_part_detail = kwargs.pop('sub_part_detail', True)
pricing = kwargs.pop('pricing', True)
substitutes = kwargs.pop('substitutes', True)
super().__init__(*args, **kwargs)
if isGeneratingSchema():
return
if not part_detail:
self.fields.pop('part_detail', None)
if not sub_part_detail:
self.fields.pop('sub_part_detail', None)
if not can_build:
self.fields.pop('can_build')
if not substitutes:
self.fields.pop('substitutes', None)
# TODO INVE-T1 support complex filters
if not pricing:
self.fields.pop('pricing_min', None)
self.fields.pop('pricing_max', None)
@@ -1702,12 +1673,18 @@ class BomItemSerializer(
help_text=_('Select the parent assembly'),
)
substitutes = BomItemSubstituteSerializer(
many=True, read_only=True, allow_null=True
substitutes = can_filter(
BomItemSubstituteSerializer(many=True, read_only=True, allow_null=True), True
)
part_detail = PartBriefSerializer(
source='part', label=_('Assembly'), many=False, read_only=True, allow_null=True
part_detail = can_filter(
PartBriefSerializer(
source='part',
label=_('Assembly'),
many=False,
read_only=True,
allow_null=True,
)
)
sub_part = serializers.PrimaryKeyRelatedField(
@@ -1716,12 +1693,15 @@ class BomItemSerializer(
help_text=_('Select the component part'),
)
sub_part_detail = PartBriefSerializer(
source='sub_part',
label=_('Component'),
many=False,
read_only=True,
allow_null=True,
sub_part_detail = can_filter(
PartBriefSerializer(
source='sub_part',
label=_('Component'),
many=False,
read_only=True,
allow_null=True,
),
True,
)
on_order = serializers.FloatField(
@@ -1732,8 +1712,9 @@ class BomItemSerializer(
label=_('In Production'), read_only=True, allow_null=True
)
can_build = serializers.FloatField(
label=_('Can Build'), read_only=True, allow_null=True
can_build = can_filter(
serializers.FloatField(label=_('Can Build'), read_only=True, allow_null=True),
True,
)
# Cached pricing fields

View File

@@ -37,6 +37,8 @@ from InvenTree.serializers import (
InvenTreeCurrencySerializer,
InvenTreeDecimalField,
InvenTreeModelSerializer,
PathScopedMixin,
can_filter,
)
from users.serializers import UserSerializer
@@ -222,23 +224,9 @@ class StockItemTestResultSerializer(
read_only_fields = ['pk', 'user', 'date']
def __init__(self, *args, **kwargs):
"""Add detail fields."""
user_detail = kwargs.pop('user_detail', False)
template_detail = kwargs.pop('template_detail', False)
super().__init__(*args, **kwargs)
if isGeneratingSchema():
return
if user_detail is not True:
self.fields.pop('user_detail', None)
if template_detail is not True:
self.fields.pop('template_detail', None)
user_detail = UserSerializer(source='user', read_only=True, allow_null=True)
user_detail = can_filter(
UserSerializer(source='user', read_only=True, allow_null=True)
)
template = serializers.PrimaryKeyRelatedField(
queryset=part_models.PartTestTemplate.objects.all(),
@@ -249,8 +237,10 @@ class StockItemTestResultSerializer(
label=_('Test template for this result'),
)
template_detail = part_serializers.PartTestTemplateSerializer(
source='template', read_only=True, allow_null=True
template_detail = can_filter(
part_serializers.PartTestTemplateSerializer(
source='template', read_only=True, allow_null=True
)
)
attachment = InvenTree.serializers.InvenTreeAttachmentSerializerField(
@@ -415,30 +405,14 @@ class StockItemSerializer(
def __init__(self, *args, **kwargs):
"""Add detail fields."""
part_detail = kwargs.pop('part_detail', True)
location_detail = kwargs.pop('location_detail', True)
supplier_part_detail = kwargs.pop('supplier_part_detail', True)
path_detail = kwargs.pop('path_detail', False)
tests = kwargs.pop('tests', False)
super().__init__(*args, **kwargs)
if isGeneratingSchema():
return
if not part_detail:
self.fields.pop('part_detail', None)
if not location_detail:
self.fields.pop('location_detail', None)
if not supplier_part_detail:
self.fields.pop('supplier_part_detail', None)
if not tests:
self.fields.pop('tests', None)
# TODO INVE-T1 support complex filters
if not path_detail:
self.fields.pop('location_path', None)
@@ -613,32 +587,43 @@ class StockItemSerializer(
)
# Optional detail fields, which can be appended via query parameters
supplier_part_detail = company_serializers.SupplierPartSerializer(
label=_('Supplier Part'),
source='supplier_part',
brief=True,
supplier_detail=False,
manufacturer_detail=False,
part_detail=False,
many=False,
read_only=True,
allow_null=True,
supplier_part_detail = can_filter(
company_serializers.SupplierPartSerializer(
label=_('Supplier Part'),
source='supplier_part',
brief=True,
supplier_detail=False,
manufacturer_detail=False,
part_detail=False,
many=False,
read_only=True,
allow_null=True,
),
True,
)
part_detail = part_serializers.PartBriefSerializer(
label=_('Part'), source='part', many=False, read_only=True, allow_null=True
part_detail = can_filter(
part_serializers.PartBriefSerializer(
label=_('Part'), source='part', many=False, read_only=True, allow_null=True
),
True,
)
location_detail = LocationBriefSerializer(
label=_('Location'),
source='location',
many=False,
read_only=True,
allow_null=True,
location_detail = can_filter(
LocationBriefSerializer(
label=_('Location'),
source='location',
many=False,
read_only=True,
allow_null=True,
),
True,
)
tests = StockItemTestResultSerializer(
source='test_results', many=True, read_only=True, allow_null=True
tests = can_filter(
StockItemTestResultSerializer(
source='test_results', many=True, read_only=True, allow_null=True
)
)
quantity = InvenTreeDecimalField()
@@ -1189,6 +1174,7 @@ class LocationSerializer(
super().__init__(*args, **kwargs)
# TODO INVE-T1 support complex filters
if not path_detail and not isGeneratingSchema():
self.fields.pop('path', None)
@@ -1241,7 +1227,9 @@ class LocationSerializer(
@register_importer()
class StockTrackingSerializer(
DataImportExportSerializerMixin, InvenTree.serializers.InvenTreeModelSerializer
DataImportExportSerializerMixin,
PathScopedMixin,
InvenTree.serializers.InvenTreeModelSerializer,
):
"""Serializer for StockItemTracking model."""
@@ -1264,30 +1252,14 @@ class StockTrackingSerializer(
read_only_fields = ['date', 'user', 'label', 'tracking_type']
def __init__(self, *args, **kwargs):
"""Add detail fields."""
item_detail = kwargs.pop('item_detail', False)
user_detail = kwargs.pop('user_detail', False)
super().__init__(*args, **kwargs)
if isGeneratingSchema():
return
if item_detail is not True:
self.fields.pop('item_detail', None)
if user_detail is not True:
self.fields.pop('user_detail', None)
label = serializers.CharField(read_only=True)
item_detail = StockItemSerializer(
source='item', many=False, read_only=True, allow_null=True
item_detail = can_filter(
StockItemSerializer(source='item', many=False, read_only=True, allow_null=True)
)
user_detail = UserSerializer(
source='user', many=False, read_only=True, allow_null=True
user_detail = can_filter(
UserSerializer(source='user', many=False, read_only=True, allow_null=True)
)
deltas = serializers.JSONField(read_only=True)

View File

@@ -245,6 +245,7 @@ class GroupSerializer(InvenTreeModelSerializer):
def __init__(self, *args, **kwargs):
"""Initialize this serializer with extra fields as required."""
# TODO INVE-T1 support complex filters
role_detail = kwargs.pop('role_detail', False)
user_detail = kwargs.pop('user_detail', False)
permission_detail = kwargs.pop('permission_detail', False)