mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-30 20:55:42 +00:00 
			
		
		
		
	Merge pull request from GHSA-7rq4-qcpw-74gq
This commit is contained in:
		
							
								
								
									
										33
									
								
								InvenTree/InvenTree/admin.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								InvenTree/InvenTree/admin.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | """Admin classes""" | ||||||
|  |  | ||||||
|  | from import_export.resources import ModelResource | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class InvenTreeResource(ModelResource): | ||||||
|  |     """Custom subclass of the ModelResource class provided by django-import-export" | ||||||
|  |  | ||||||
|  |     Ensures that exported data are escaped to prevent malicious formula injection. | ||||||
|  |     Ref: https://owasp.org/www-community/attacks/CSV_Injection | ||||||
|  |     """ | ||||||
|  |  | ||||||
|  |     def export_resource(self, obj): | ||||||
|  |         """Custom function to override default row export behaviour. | ||||||
|  |  | ||||||
|  |         Specifically, strip illegal leading characters to prevent formula injection | ||||||
|  |         """ | ||||||
|  |         row = super().export_resource(obj) | ||||||
|  |  | ||||||
|  |         illegal_start_vals = ['@', '=', '+', '-', '@', '\t', '\r', '\n'] | ||||||
|  |  | ||||||
|  |         for idx, val in enumerate(row): | ||||||
|  |             if type(val) is str: | ||||||
|  |                 val = val.strip() | ||||||
|  |  | ||||||
|  |                 # If the value starts with certain 'suspicious' values, remove it! | ||||||
|  |                 while len(val) > 0 and val[0] in illegal_start_vals: | ||||||
|  |                     # Remove the first character | ||||||
|  |                     val = val[1:] | ||||||
|  |  | ||||||
|  |                 row[idx] = val | ||||||
|  |  | ||||||
|  |         return row | ||||||
| @@ -2,16 +2,15 @@ from django.contrib import admin | |||||||
|  |  | ||||||
| from import_export.admin import ImportExportModelAdmin | from import_export.admin import ImportExportModelAdmin | ||||||
| from import_export.fields import Field | from import_export.fields import Field | ||||||
| from import_export.resources import ModelResource |  | ||||||
| import import_export.widgets as widgets | import import_export.widgets as widgets | ||||||
|  |  | ||||||
| from build.models import Build, BuildItem | from build.models import Build, BuildItem | ||||||
|  | from InvenTree.admin import InvenTreeResource | ||||||
| import part.models | import part.models | ||||||
|  |  | ||||||
|  |  | ||||||
| class BuildResource(ModelResource): | class BuildResource(InvenTreeResource): | ||||||
|     """Class for managing import/export of Build data""" |     """Class for managing import/export of Build data.""" | ||||||
|     # For some reason, we need to specify the fields individually for this ModelResource, |     # For some reason, we need to specify the fields individually for this ModelResource, | ||||||
|     # but we don't for other ones. |     # but we don't for other ones. | ||||||
|     # TODO: 2022-05-12 - Need to investigate why this is the case! |     # TODO: 2022-05-12 - Need to investigate why this is the case! | ||||||
|   | |||||||
| @@ -3,8 +3,8 @@ from django.contrib import admin | |||||||
| import import_export.widgets as widgets | import import_export.widgets as widgets | ||||||
| from import_export.admin import ImportExportModelAdmin | from import_export.admin import ImportExportModelAdmin | ||||||
| from import_export.fields import Field | from import_export.fields import Field | ||||||
| from import_export.resources import ModelResource |  | ||||||
|  |  | ||||||
|  | from InvenTree.admin import InvenTreeResource | ||||||
| from part.models import Part | from part.models import Part | ||||||
|  |  | ||||||
| from .models import (Company, ManufacturerPart, ManufacturerPartAttachment, | from .models import (Company, ManufacturerPart, ManufacturerPartAttachment, | ||||||
| @@ -12,8 +12,8 @@ from .models import (Company, ManufacturerPart, ManufacturerPartAttachment, | |||||||
|                      SupplierPriceBreak) |                      SupplierPriceBreak) | ||||||
|  |  | ||||||
|  |  | ||||||
| class CompanyResource(ModelResource): | class CompanyResource(InvenTreeResource): | ||||||
|     """ Class for managing Company data import/export """ |     """Class for managing Company data import/export.""" | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|         model = Company |         model = Company | ||||||
| @@ -34,10 +34,8 @@ class CompanyAdmin(ImportExportModelAdmin): | |||||||
|     ] |     ] | ||||||
|  |  | ||||||
|  |  | ||||||
| class SupplierPartResource(ModelResource): | class SupplierPartResource(InvenTreeResource): | ||||||
|     """ |     """Class for managing SupplierPart data import/export.""" | ||||||
|     Class for managing SupplierPart data import/export |  | ||||||
|     """ |  | ||||||
|  |  | ||||||
|     part = Field(attribute='part', widget=widgets.ForeignKeyWidget(Part)) |     part = Field(attribute='part', widget=widgets.ForeignKeyWidget(Part)) | ||||||
|  |  | ||||||
| @@ -70,10 +68,8 @@ class SupplierPartAdmin(ImportExportModelAdmin): | |||||||
|     autocomplete_fields = ('part', 'supplier', 'manufacturer_part',) |     autocomplete_fields = ('part', 'supplier', 'manufacturer_part',) | ||||||
|  |  | ||||||
|  |  | ||||||
| class ManufacturerPartResource(ModelResource): | class ManufacturerPartResource(InvenTreeResource): | ||||||
|     """ |     """Class for managing ManufacturerPart data import/export.""" | ||||||
|     Class for managing ManufacturerPart data import/export |  | ||||||
|     """ |  | ||||||
|  |  | ||||||
|     part = Field(attribute='part', widget=widgets.ForeignKeyWidget(Part)) |     part = Field(attribute='part', widget=widgets.ForeignKeyWidget(Part)) | ||||||
|  |  | ||||||
| @@ -118,10 +114,8 @@ class ManufacturerPartAttachmentAdmin(ImportExportModelAdmin): | |||||||
|     autocomplete_fields = ('manufacturer_part',) |     autocomplete_fields = ('manufacturer_part',) | ||||||
|  |  | ||||||
|  |  | ||||||
| class ManufacturerPartParameterResource(ModelResource): | class ManufacturerPartParameterResource(InvenTreeResource): | ||||||
|     """ |     """Class for managing ManufacturerPartParameter data import/export.""" | ||||||
|     Class for managing ManufacturerPartParameter data import/export |  | ||||||
|     """ |  | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|         model = ManufacturerPartParameter |         model = ManufacturerPartParameter | ||||||
| @@ -148,8 +142,8 @@ class ManufacturerPartParameterAdmin(ImportExportModelAdmin): | |||||||
|     autocomplete_fields = ('manufacturer_part',) |     autocomplete_fields = ('manufacturer_part',) | ||||||
|  |  | ||||||
|  |  | ||||||
| class SupplierPriceBreakResource(ModelResource): | class SupplierPriceBreakResource(InvenTreeResource): | ||||||
|     """ Class for managing SupplierPriceBreak data import/export """ |     """Class for managing SupplierPriceBreak data import/export.""" | ||||||
|  |  | ||||||
|     part = Field(attribute='part', widget=widgets.ForeignKeyWidget(SupplierPart)) |     part = Field(attribute='part', widget=widgets.ForeignKeyWidget(SupplierPart)) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,9 +1,12 @@ | |||||||
|  | """Admin functionality for the 'order' app""" | ||||||
|  |  | ||||||
| from django.contrib import admin | from django.contrib import admin | ||||||
|  |  | ||||||
| import import_export.widgets as widgets | import import_export.widgets as widgets | ||||||
| from import_export.admin import ImportExportModelAdmin | from import_export.admin import ImportExportModelAdmin | ||||||
| from import_export.fields import Field | from import_export.fields import Field | ||||||
| from import_export.resources import ModelResource |  | ||||||
|  | from InvenTree.admin import InvenTreeResource | ||||||
|  |  | ||||||
| from .models import (PurchaseOrder, PurchaseOrderExtraLine, | from .models import (PurchaseOrder, PurchaseOrderExtraLine, | ||||||
|                      PurchaseOrderLineItem, SalesOrder, SalesOrderAllocation, |                      PurchaseOrderLineItem, SalesOrder, SalesOrderAllocation, | ||||||
| @@ -13,6 +16,7 @@ from .models import (PurchaseOrder, PurchaseOrderExtraLine, | |||||||
|  |  | ||||||
| # region general classes | # region general classes | ||||||
| class GeneralExtraLineAdmin: | class GeneralExtraLineAdmin: | ||||||
|  |     """Admin class template for the 'ExtraLineItem' models""" | ||||||
|     list_display = ( |     list_display = ( | ||||||
|         'order', |         'order', | ||||||
|         'quantity', |         'quantity', | ||||||
| @@ -29,6 +33,7 @@ class GeneralExtraLineAdmin: | |||||||
|  |  | ||||||
|  |  | ||||||
| class GeneralExtraLineMeta: | class GeneralExtraLineMeta: | ||||||
|  |     """Metaclass template for the 'ExtraLineItem' models""" | ||||||
|     skip_unchanged = True |     skip_unchanged = True | ||||||
|     report_skipped = False |     report_skipped = False | ||||||
|     clean_model_instances = True |     clean_model_instances = True | ||||||
| @@ -36,11 +41,13 @@ class GeneralExtraLineMeta: | |||||||
|  |  | ||||||
|  |  | ||||||
| class PurchaseOrderLineItemInlineAdmin(admin.StackedInline): | class PurchaseOrderLineItemInlineAdmin(admin.StackedInline): | ||||||
|  |     """Inline admin class for the PurchaseOrderLineItem model""" | ||||||
|     model = PurchaseOrderLineItem |     model = PurchaseOrderLineItem | ||||||
|     extra = 0 |     extra = 0 | ||||||
|  |  | ||||||
|  |  | ||||||
| class PurchaseOrderAdmin(ImportExportModelAdmin): | class PurchaseOrderAdmin(ImportExportModelAdmin): | ||||||
|  |     """Admin class for the PurchaseOrder model""" | ||||||
|  |  | ||||||
|     exclude = [ |     exclude = [ | ||||||
|         'reference_int', |         'reference_int', | ||||||
| @@ -68,6 +75,7 @@ class PurchaseOrderAdmin(ImportExportModelAdmin): | |||||||
|  |  | ||||||
|  |  | ||||||
| class SalesOrderAdmin(ImportExportModelAdmin): | class SalesOrderAdmin(ImportExportModelAdmin): | ||||||
|  |     """Admin class for the SalesOrder model""" | ||||||
|  |  | ||||||
|     exclude = [ |     exclude = [ | ||||||
|         'reference_int', |         'reference_int', | ||||||
| @@ -90,10 +98,8 @@ class SalesOrderAdmin(ImportExportModelAdmin): | |||||||
|     autocomplete_fields = ('customer',) |     autocomplete_fields = ('customer',) | ||||||
|  |  | ||||||
|  |  | ||||||
| class PurchaseOrderResource(ModelResource): | class PurchaseOrderResource(InvenTreeResource): | ||||||
|     """ |     """Class for managing import / export of PurchaseOrder data.""" | ||||||
|     Class for managing import / export of PurchaseOrder data |  | ||||||
|     """ |  | ||||||
|  |  | ||||||
|     # Add number of line items |     # Add number of line items | ||||||
|     line_items = Field(attribute='line_count', widget=widgets.IntegerWidget(), readonly=True) |     line_items = Field(attribute='line_count', widget=widgets.IntegerWidget(), readonly=True) | ||||||
| @@ -102,6 +108,7 @@ class PurchaseOrderResource(ModelResource): | |||||||
|     overdue = Field(attribute='is_overdue', widget=widgets.BooleanWidget(), readonly=True) |     overdue = Field(attribute='is_overdue', widget=widgets.BooleanWidget(), readonly=True) | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|  |         """Metaclass""" | ||||||
|         model = PurchaseOrder |         model = PurchaseOrder | ||||||
|         skip_unchanged = True |         skip_unchanged = True | ||||||
|         clean_model_instances = True |         clean_model_instances = True | ||||||
| @@ -110,8 +117,8 @@ class PurchaseOrderResource(ModelResource): | |||||||
|         ] |         ] | ||||||
|  |  | ||||||
|  |  | ||||||
| class PurchaseOrderLineItemResource(ModelResource): | class PurchaseOrderLineItemResource(InvenTreeResource): | ||||||
|     """ Class for managing import / export of PurchaseOrderLineItem data """ |     """Class for managing import / export of PurchaseOrderLineItem data.""" | ||||||
|  |  | ||||||
|     part_name = Field(attribute='part__part__name', readonly=True) |     part_name = Field(attribute='part__part__name', readonly=True) | ||||||
|  |  | ||||||
| @@ -122,23 +129,24 @@ class PurchaseOrderLineItemResource(ModelResource): | |||||||
|     SKU = Field(attribute='part__SKU', readonly=True) |     SKU = Field(attribute='part__SKU', readonly=True) | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|  |         """Metaclass""" | ||||||
|         model = PurchaseOrderLineItem |         model = PurchaseOrderLineItem | ||||||
|         skip_unchanged = True |         skip_unchanged = True | ||||||
|         report_skipped = False |         report_skipped = False | ||||||
|         clean_model_instances = True |         clean_model_instances = True | ||||||
|  |  | ||||||
|  |  | ||||||
| class PurchaseOrderExtraLineResource(ModelResource): | class PurchaseOrderExtraLineResource(InvenTreeResource): | ||||||
|     """ Class for managing import / export of PurchaseOrderExtraLine data """ |     """Class for managing import / export of PurchaseOrderExtraLine data.""" | ||||||
|  |  | ||||||
|     class Meta(GeneralExtraLineMeta): |     class Meta(GeneralExtraLineMeta): | ||||||
|  |         """Metaclass options.""" | ||||||
|  |  | ||||||
|         model = PurchaseOrderExtraLine |         model = PurchaseOrderExtraLine | ||||||
|  |  | ||||||
|  |  | ||||||
| class SalesOrderResource(ModelResource): | class SalesOrderResource(InvenTreeResource): | ||||||
|     """ |     """Class for managing import / export of SalesOrder data.""" | ||||||
|     Class for managing import / export of SalesOrder data |  | ||||||
|     """ |  | ||||||
|  |  | ||||||
|     # Add number of line items |     # Add number of line items | ||||||
|     line_items = Field(attribute='line_count', widget=widgets.IntegerWidget(), readonly=True) |     line_items = Field(attribute='line_count', widget=widgets.IntegerWidget(), readonly=True) | ||||||
| @@ -147,6 +155,7 @@ class SalesOrderResource(ModelResource): | |||||||
|     overdue = Field(attribute='is_overdue', widget=widgets.BooleanWidget(), readonly=True) |     overdue = Field(attribute='is_overdue', widget=widgets.BooleanWidget(), readonly=True) | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|  |         """Metaclass options""" | ||||||
|         model = SalesOrder |         model = SalesOrder | ||||||
|         skip_unchanged = True |         skip_unchanged = True | ||||||
|         clean_model_instances = True |         clean_model_instances = True | ||||||
| @@ -155,10 +164,8 @@ class SalesOrderResource(ModelResource): | |||||||
|         ] |         ] | ||||||
|  |  | ||||||
|  |  | ||||||
| class SalesOrderLineItemResource(ModelResource): | class SalesOrderLineItemResource(InvenTreeResource): | ||||||
|     """ |     """Class for managing import / export of SalesOrderLineItem data.""" | ||||||
|     Class for managing import / export of SalesOrderLineItem data |  | ||||||
|     """ |  | ||||||
|  |  | ||||||
|     part_name = Field(attribute='part__name', readonly=True) |     part_name = Field(attribute='part__name', readonly=True) | ||||||
|  |  | ||||||
| @@ -169,31 +176,34 @@ class SalesOrderLineItemResource(ModelResource): | |||||||
|     fulfilled = Field(attribute='fulfilled_quantity', readonly=True) |     fulfilled = Field(attribute='fulfilled_quantity', readonly=True) | ||||||
|  |  | ||||||
|     def dehydrate_sale_price(self, item): |     def dehydrate_sale_price(self, item): | ||||||
|         """ |         """Return a string value of the 'sale_price' field, rather than the 'Money' object. | ||||||
|         Return a string value of the 'sale_price' field, rather than the 'Money' object. |  | ||||||
|         Ref: https://github.com/inventree/InvenTree/issues/2207 |         Ref: https://github.com/inventree/InvenTree/issues/2207 | ||||||
|         """ |         """ | ||||||
|  |  | ||||||
|         if item.sale_price: |         if item.sale_price: | ||||||
|             return str(item.sale_price) |             return str(item.sale_price) | ||||||
|         else: |         else: | ||||||
|             return '' |             return '' | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|  |         """Metaclass options""" | ||||||
|         model = SalesOrderLineItem |         model = SalesOrderLineItem | ||||||
|         skip_unchanged = True |         skip_unchanged = True | ||||||
|         report_skipped = False |         report_skipped = False | ||||||
|         clean_model_instances = True |         clean_model_instances = True | ||||||
|  |  | ||||||
|  |  | ||||||
| class SalesOrderExtraLineResource(ModelResource): | class SalesOrderExtraLineResource(InvenTreeResource): | ||||||
|     """ Class for managing import / export of SalesOrderExtraLine data """ |     """Class for managing import / export of SalesOrderExtraLine data.""" | ||||||
|  |  | ||||||
|     class Meta(GeneralExtraLineMeta): |     class Meta(GeneralExtraLineMeta): | ||||||
|  |         """Metaclass options.""" | ||||||
|  |  | ||||||
|         model = SalesOrderExtraLine |         model = SalesOrderExtraLine | ||||||
|  |  | ||||||
|  |  | ||||||
| class PurchaseOrderLineItemAdmin(ImportExportModelAdmin): | class PurchaseOrderLineItemAdmin(ImportExportModelAdmin): | ||||||
|  |     """Admin class for the PurchaseOrderLine model""" | ||||||
|  |  | ||||||
|     resource_class = PurchaseOrderLineItemResource |     resource_class = PurchaseOrderLineItemResource | ||||||
|  |  | ||||||
| @@ -210,11 +220,12 @@ class PurchaseOrderLineItemAdmin(ImportExportModelAdmin): | |||||||
|  |  | ||||||
|  |  | ||||||
| class PurchaseOrderExtraLineAdmin(GeneralExtraLineAdmin, ImportExportModelAdmin): | class PurchaseOrderExtraLineAdmin(GeneralExtraLineAdmin, ImportExportModelAdmin): | ||||||
|  |     """Admin class for the PurchaseOrderExtraLine model""" | ||||||
|     resource_class = PurchaseOrderExtraLineResource |     resource_class = PurchaseOrderExtraLineResource | ||||||
|  |  | ||||||
|  |  | ||||||
| class SalesOrderLineItemAdmin(ImportExportModelAdmin): | class SalesOrderLineItemAdmin(ImportExportModelAdmin): | ||||||
|  |     """Admin class for the SalesOrderLine model""" | ||||||
|  |  | ||||||
|     resource_class = SalesOrderLineItemResource |     resource_class = SalesOrderLineItemResource | ||||||
|  |  | ||||||
| @@ -236,11 +247,12 @@ class SalesOrderLineItemAdmin(ImportExportModelAdmin): | |||||||
|  |  | ||||||
|  |  | ||||||
| class SalesOrderExtraLineAdmin(GeneralExtraLineAdmin, ImportExportModelAdmin): | class SalesOrderExtraLineAdmin(GeneralExtraLineAdmin, ImportExportModelAdmin): | ||||||
|  |     """Admin class for the SalesOrderExtraLine model""" | ||||||
|     resource_class = SalesOrderExtraLineResource |     resource_class = SalesOrderExtraLineResource | ||||||
|  |  | ||||||
|  |  | ||||||
| class SalesOrderShipmentAdmin(ImportExportModelAdmin): | class SalesOrderShipmentAdmin(ImportExportModelAdmin): | ||||||
|  |     """Admin class for the SalesOrderShipment model""" | ||||||
|  |  | ||||||
|     list_display = [ |     list_display = [ | ||||||
|         'order', |         'order', | ||||||
| @@ -258,6 +270,7 @@ class SalesOrderShipmentAdmin(ImportExportModelAdmin): | |||||||
|  |  | ||||||
|  |  | ||||||
| class SalesOrderAllocationAdmin(ImportExportModelAdmin): | class SalesOrderAllocationAdmin(ImportExportModelAdmin): | ||||||
|  |     """Admin class for the SalesOrderAllocation model""" | ||||||
|  |  | ||||||
|     list_display = ( |     list_display = ( | ||||||
|         'line', |         'line', | ||||||
|   | |||||||
| @@ -3,15 +3,15 @@ from django.contrib import admin | |||||||
| import import_export.widgets as widgets | import import_export.widgets as widgets | ||||||
| from import_export.admin import ImportExportModelAdmin | from import_export.admin import ImportExportModelAdmin | ||||||
| from import_export.fields import Field | from import_export.fields import Field | ||||||
| from import_export.resources import ModelResource |  | ||||||
|  |  | ||||||
| import part.models as models | import part.models as models | ||||||
| from company.models import SupplierPart | from company.models import SupplierPart | ||||||
|  | from InvenTree.admin import InvenTreeResource | ||||||
| from stock.models import StockLocation | from stock.models import StockLocation | ||||||
|  |  | ||||||
|  |  | ||||||
| class PartResource(ModelResource): | class PartResource(InvenTreeResource): | ||||||
|     """ Class for managing Part data import/export """ |     """Class for managing Part data import/export.""" | ||||||
|  |  | ||||||
|     # ForeignKey fields |     # ForeignKey fields | ||||||
|     category = Field(attribute='category', widget=widgets.ForeignKeyWidget(models.PartCategory)) |     category = Field(attribute='category', widget=widgets.ForeignKeyWidget(models.PartCategory)) | ||||||
| @@ -81,8 +81,8 @@ class PartAdmin(ImportExportModelAdmin): | |||||||
|     ] |     ] | ||||||
|  |  | ||||||
|  |  | ||||||
| class PartCategoryResource(ModelResource): | class PartCategoryResource(InvenTreeResource): | ||||||
|     """ Class for managing PartCategory data import/export """ |     """Class for managing PartCategory data import/export.""" | ||||||
|  |  | ||||||
|     parent = Field(attribute='parent', widget=widgets.ForeignKeyWidget(models.PartCategory)) |     parent = Field(attribute='parent', widget=widgets.ForeignKeyWidget(models.PartCategory)) | ||||||
|  |  | ||||||
| @@ -157,8 +157,8 @@ class PartTestTemplateAdmin(admin.ModelAdmin): | |||||||
|     autocomplete_fields = ('part',) |     autocomplete_fields = ('part',) | ||||||
|  |  | ||||||
|  |  | ||||||
| class BomItemResource(ModelResource): | class BomItemResource(InvenTreeResource): | ||||||
|     """ Class for managing BomItem data import/export """ |     """Class for managing BomItem data import/export.""" | ||||||
|  |  | ||||||
|     level = Field(attribute='level', readonly=True) |     level = Field(attribute='level', readonly=True) | ||||||
|  |  | ||||||
| @@ -269,8 +269,8 @@ class ParameterTemplateAdmin(ImportExportModelAdmin): | |||||||
|     search_fields = ('name', 'units') |     search_fields = ('name', 'units') | ||||||
|  |  | ||||||
|  |  | ||||||
| class ParameterResource(ModelResource): | class ParameterResource(InvenTreeResource): | ||||||
|     """ Class for managing PartParameter data import/export """ |     """Class for managing PartParameter data import/export.""" | ||||||
|  |  | ||||||
|     part = Field(attribute='part', widget=widgets.ForeignKeyWidget(models.Part)) |     part = Field(attribute='part', widget=widgets.ForeignKeyWidget(models.Part)) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3,10 +3,10 @@ from django.contrib import admin | |||||||
| import import_export.widgets as widgets | import import_export.widgets as widgets | ||||||
| from import_export.admin import ImportExportModelAdmin | from import_export.admin import ImportExportModelAdmin | ||||||
| from import_export.fields import Field | from import_export.fields import Field | ||||||
| from import_export.resources import ModelResource |  | ||||||
|  |  | ||||||
| from build.models import Build | from build.models import Build | ||||||
| from company.models import Company, SupplierPart | from company.models import Company, SupplierPart | ||||||
|  | from InvenTree.admin import InvenTreeResource | ||||||
| from order.models import PurchaseOrder, SalesOrder | from order.models import PurchaseOrder, SalesOrder | ||||||
| from part.models import Part | from part.models import Part | ||||||
|  |  | ||||||
| @@ -14,8 +14,8 @@ from .models import (StockItem, StockItemAttachment, StockItemTestResult, | |||||||
|                      StockItemTracking, StockLocation) |                      StockItemTracking, StockLocation) | ||||||
|  |  | ||||||
|  |  | ||||||
| class LocationResource(ModelResource): | class LocationResource(InvenTreeResource): | ||||||
|     """ Class for managing StockLocation data import/export """ |     """Class for managing StockLocation data import/export.""" | ||||||
|  |  | ||||||
|     parent = Field(attribute='parent', widget=widgets.ForeignKeyWidget(StockLocation)) |     parent = Field(attribute='parent', widget=widgets.ForeignKeyWidget(StockLocation)) | ||||||
|  |  | ||||||
| @@ -65,8 +65,8 @@ class LocationAdmin(ImportExportModelAdmin): | |||||||
|     ] |     ] | ||||||
|  |  | ||||||
|  |  | ||||||
| class StockItemResource(ModelResource): | class StockItemResource(InvenTreeResource): | ||||||
|     """ Class for managing StockItem data import/export """ |     """Class for managing StockItem data import/export.""" | ||||||
|  |  | ||||||
|     # Custom managers for ForeignKey fields |     # Custom managers for ForeignKey fields | ||||||
|     part = Field(attribute='part', widget=widgets.ForeignKeyWidget(Part)) |     part = Field(attribute='part', widget=widgets.ForeignKeyWidget(Part)) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user