Improved Part API

This commit is contained in:
Oliver Walters 2017-04-14 11:46:18 +10:00
parent 817a67cd41
commit 39a6bcdf3e
4 changed files with 96 additions and 32 deletions

View File

@ -95,13 +95,8 @@ class PartParameterTemplate(models.Model):
A PartParameterTemplate can be optionally associated with a PartCategory
"""
name = models.CharField(max_length=20)
description = models.CharField(max_length=100, blank=True)
units = models.CharField(max_length=10, blank=True)
default_value = models.CharField(max_length=50, blank=True)
default_min = models.CharField(max_length=50, blank=True)
default_max = models.CharField(max_length=50, blank=True)
# Parameter format
PARAM_NUMERIC = 10
PARAM_TEXT = 20
@ -143,10 +138,31 @@ class CategoryParameterLink(models.Model):
verbose_name_plural = "Category Parameters"
class PartParameterManager(models.Manager):
""" Manager for handling PartParameter objects
"""
def create(self, *args, **kwargs):
""" Prevent creation of duplicate PartParameter
"""
part_id = kwargs['part']
template_id = kwargs['template']
try:
params = self.filter(part=part_id, template=template_id)
return params[0]
except:
pass
return super(PartParameterManager, self).create(*args, **kwargs)
class PartParameter(models.Model):
""" PartParameter is associated with a single part
"""
objects = PartParameterManager()
part = models.ForeignKey(Part, on_delete=models.CASCADE, related_name='parameters')
template = models.ForeignKey(PartParameterTemplate)
@ -155,17 +171,6 @@ class PartParameter(models.Model):
min_value = models.CharField(max_length=50, blank=True)
max_value = models.CharField(max_length=50, blank=True)
# Prevent multiple parameters of the same template
# from being added to the same part
def save(self, *args, **kwargs):
params = PartParameter.objects.filter(part=self.part, template=self.template)
if len(params) > 1:
return
if len(params) == 1 and params[0].id != self.id:
return
super(PartParameter, self).save(*args, **kwargs)
def __str__(self):
return "{name} : {val}{units}".format(
name=self.template.name,

View File

@ -1,6 +1,6 @@
from rest_framework import serializers
from .models import Part, PartCategory, PartParameter
from .models import Part, PartCategory, PartParameter, PartParameterTemplate
class PartParameterSerializer(serializers.ModelSerializer):
@ -58,3 +58,13 @@ class PartCategoryDetailSerializer(serializers.ModelSerializer):
'path',
'children',
'parts')
class PartTemplateSerializer(serializers.ModelSerializer):
class Meta:
model = PartParameterTemplate
fields = ('pk',
'name',
'units',
'format')

View File

@ -16,16 +16,24 @@ categorypatterns = [
url(r'^$', views.PartCategoryList.as_view())
]
""" URL patterns associated with a particular part:
/part/<pk> -> Detail view of a given part
/part/<pk>/parameters -> List parameters associated with a part
"""
partdetailpatterns = [
# Single part detail
url(r'^$', views.PartDetail.as_view()),
partparampatterns = [
# Detail of a single part parameter
url(r'^(?P<pk>[0-9]+)/$', views.PartParamDetail.as_view()),
# Parameters associated with a particular part
url(r'^\?[^/]*/$', views.PartParamList.as_view()),
# All part parameters
url(r'^$', views.PartParamList.as_view()),
]
parttemplatepatterns = [
# Detail of a single part field template
url(r'^(?P<pk>[0-9]+)/$', views.PartTemplateDetail.as_view()),
# List all part field templates
url(r'^$', views.PartTemplateList.as_view())
# View part parameters
url(r'parameters/$', views.PartParameters.as_view())
]
""" Top-level URL patterns for the Part app:
@ -36,11 +44,17 @@ partdetailpatterns = [
"""
urlpatterns = [
# Individual part
url(r'^(?P<pk>[0-9]+)/', include(partdetailpatterns)),
url(r'^(?P<pk>[0-9]+)/$', views.PartDetail.as_view()),
# Part categories
url(r'^category/', views.PartCategoryList.as_view()),
# Part parameters
url(r'^parameters/', include(partparampatterns)),
# Part templates
url(r'^templates/', include(parttemplatepatterns)),
# List of all parts
url(r'^$', views.PartList.as_view())
]

View File

@ -1,9 +1,10 @@
from rest_framework import generics, permissions
from .models import PartCategory, Part, PartParameter
from .models import PartCategory, Part, PartParameter, PartParameterTemplate
from .serializers import PartSerializer
from .serializers import PartCategoryDetailSerializer
from .serializers import PartParameterSerializer
from .serializers import PartTemplateSerializer
class PartDetail(generics.RetrieveUpdateDestroyAPIView):
@ -14,13 +15,33 @@ class PartDetail(generics.RetrieveUpdateDestroyAPIView):
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
class PartParameters(generics.ListCreateAPIView):
class PartParamList(generics.ListCreateAPIView):
""" Return all parameters associated with a particular part
"""
def get_queryset(self):
part_id = self.kwargs['pk']
return PartParameter.objects.filter(part=part_id)
part_id = self.request.query_params.get('part', None)
if part_id:
return PartParameter.objects.filter(part=part_id)
else:
return PartParameter.objects.all()
serializer_class = PartParameterSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
def create(self, request, *args, **kwargs):
# Ensure part link is set correctly
part_id = self.request.query_params.get('part', None)
if part_id:
request.data['part'] = part_id
return super(PartParamList, self).create(request, *args, **kwargs)
class PartParamDetail(generics.RetrieveUpdateDestroyAPIView):
""" Detail view of a single PartParameter
"""
queryset = PartParameter.objects.all()
serializer_class = PartParameterSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
@ -32,7 +53,7 @@ class PartList(generics.ListCreateAPIView):
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
class PartCategoryDetail(generics.RetrieveUpdateAPIView):
class PartCategoryDetail(generics.RetrieveUpdateDestroyAPIView):
""" Return information on a single PartCategory
"""
queryset = PartCategory.objects.all()
@ -47,3 +68,17 @@ class PartCategoryList(generics.ListCreateAPIView):
queryset = PartCategory.objects.filter(parent=None)
serializer_class = PartCategoryDetailSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
class PartTemplateDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = PartParameterTemplate.objects.all()
serializer_class = PartTemplateSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
class PartTemplateList(generics.ListCreateAPIView):
queryset = PartParameterTemplate.objects.all()
serializer_class = PartTemplateSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)