Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add REST API to manage selected KiCad categories #100

Merged
merged 5 commits into from
Aug 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions inventree_kicad/KiCadLibraryPlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
from django.urls import include, re_path
from django.utils.translation import gettext_lazy as _

from rest_framework import routers

from InvenTree.helpers import str2bool
from common.notifications import logger
from part.models import Part, PartParameterTemplate, PartParameter
Expand Down Expand Up @@ -161,6 +163,13 @@ def setup_urls(self):

from . import viewsets

api_category_router = routers.DefaultRouter()
api_category_router.register(r'category', viewsets.CategoryApi, basename='selectedcategory')

api_urls = [
re_path('', include(api_category_router.urls)),
]

return [
re_path(r'v1/', include([
re_path(r'parts/', include([
Expand All @@ -184,6 +193,8 @@ def setup_urls(self):
re_path(r'upload(?:\.(?P<format>json))?$', self.import_meta_data, name='meta_data_upload'),
re_path(r'progress_bar_status', self.get_import_progress, name='get_import_progress'),

re_path(r'api/', include(api_urls), name='api'),

# Anything else, redirect to our top-level v1 page
re_path('^.*$', viewsets.Index.as_view(), name='kicad-index'),
]
Expand Down
25 changes: 25 additions & 0 deletions inventree_kicad/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -487,3 +487,28 @@ class Meta:

def get_name(self, category):
return category.pathstring


class KicadDetailedCategorySerializer(serializers.ModelSerializer):
"""Custom model serializer for a single KiCad category instance"""

class Meta:
"""Metaclass defining serializer fields"""
model = SelectedCategory
fields = [
'pk',
'category',
'default_symbol',
'default_footprint',
'default_reference',
'default_value_parameter_template',
'footprint_parameter_template',
]

def __init__(self, *args, **kwargs):
super(KicadDetailedCategorySerializer, self).__init__(*args, **kwargs)
request = self.context.get('request')
if request and request.method in ["POST", "PUT", "PATCH"]:
self.Meta.depth = 0
else:
self.Meta.depth = 1
Comment on lines +492 to +514
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactor suggestion for dynamic depth adjustment.

The dynamic adjustment of Meta.depth in the __init__ method could be improved for clarity. Consider using a helper method to encapsulate this logic.

Apply this refactor to improve clarity:

def __init__(self, *args, **kwargs):
    super(KicadDetailedCategorySerializer, self).__init__(*args, **kwargs)
    self.adjust_depth_based_on_request()

def adjust_depth_based_on_request(self):
    """Adjust the Meta depth based on the request method."""
    request = self.context.get('request')
    if request and request.method in ["POST", "PUT", "PATCH"]:
        self.Meta.depth = 0
    else:
        self.Meta.depth = 1

99 changes: 99 additions & 0 deletions inventree_kicad/viewsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
from InvenTree.helpers import str2bool
from part.models import PartCategory, Part

from rest_framework import viewsets as rest_viewsets

from inventree_kicad import serializers
from django.shortcuts import get_object_or_404


class Index(views.APIView):
Expand All @@ -29,6 +31,103 @@ def get(self, request, *args, **kwargs):
)


class CategoryApi(rest_viewsets.ViewSet):
from .models import SelectedCategory
queryset = SelectedCategory.objects.all()
serializer_class = serializers.KicadDetailedCategorySerializer

def get_serializer(self, *args, **kwargs):
"""Add the parent plugin instance to the serializer contenxt"""

kwargs['context'] = {'request': self.request}

return self.serializer_class(*args, **kwargs)

def get_part_parameter_id_by_name(self, name):
from .models import PartParameterTemplate

ret = None
part_parameter = None

if isinstance(name, int):
# an integer was passed to the function -> assume it's the ID already
ret = name
elif isinstance(name, str):
part_parameter = PartParameterTemplate.objects.filter(name=name).first()

if part_parameter:
ret = part_parameter.pk

return ret

def list(self, request):
from .models import SelectedCategory

queryset = SelectedCategory.objects.all()
serializer = serializers.KicadDetailedCategorySerializer(queryset, many=True)

return response.Response(serializer.data)

def retrieve(self, request, pk=None):
from .models import SelectedCategory

category = get_object_or_404(SelectedCategory, pk=pk)
serializer = serializers.KicadDetailedCategorySerializer(category)

return response.Response(serializer.data)

def partial_update(self, request, pk=None):
return self.update(request, pk, partial=True)

def update(self, request, pk=None, **kwargs):
from .models import SelectedCategory

category = get_object_or_404(SelectedCategory, pk=pk)

for parameter in ['default_value_parameter_template', 'footprint_parameter_template']:
if parameter in request.data:
request.data[parameter] = self.get_part_parameter_id_by_name(request.data.pop(parameter))

serializer = self.get_serializer(category, data=request.data, partial=kwargs.get('partial', False))
serializer.is_valid(raise_exception=True)
serializer.save()

return response.Response(serializer.data)

def create(self, request):
from part.models import PartCategory, PartParameterTemplate

part_category = get_object_or_404(PartCategory, pk=request.data.get('category'))

validated_data = {
"category": part_category,
"default_symbol": request.data.get('default_symbol', ''),
"default_footprint": request.data.get('default_footprint', ''),
"default_reference": request.data.get('default_reference', ''),
}

# Add PartParameterTemplate keys
# Allow passing the parameter name instead of the id
for parameter in ['default_value_parameter_template', 'footprint_parameter_template']:
key = 'name' if isinstance(request.data.get(parameter), str) else 'pk'
validated_data[parameter] = PartParameterTemplate.objects.filter(**{key: request.data.get(parameter)}).first()

serializer = serializers.KicadDetailedCategorySerializer()
created_category = serializer.create(validated_data)

serializer = serializers.KicadDetailedCategorySerializer(created_category)

return response.Response(serializer.data)

def destroy(self, request, pk):
from .models import SelectedCategory

category = get_object_or_404(SelectedCategory, pk=pk)
category.delete()

return response.Response(status=204)


class CategoryList(generics.ListAPIView):
"""List of available KiCad categories"""

Expand Down
Loading