mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Merge pull request #962 from eeintech/part_ipn_slug
Added PartDetailFromIPN view (subclass of PartDetail) and url pattern
This commit is contained in:
commit
700d522c3c
@ -6,7 +6,7 @@ from InvenTree.settings import *
|
||||
|
||||
# Override the 'test' database
|
||||
if 'test' in sys.argv:
|
||||
eprint('InvenTree: Running tests - Using MySQL test database')
|
||||
eprint('InvenTree: Running tests - Using PostGreSQL test database')
|
||||
|
||||
DATABASES['default'] = {
|
||||
# Ensure postgresql backend is being used
|
||||
|
@ -78,6 +78,56 @@ class PartDetailTest(PartViewTestCase):
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTrue(response.context['editing_enabled'])
|
||||
|
||||
def test_part_detail_from_ipn(self):
|
||||
"""
|
||||
Test that we can retrieve a part detail page from part IPN:
|
||||
- if no part with matching IPN -> return part index
|
||||
- if unique IPN match -> return part detail page
|
||||
- if multiple IPN matches -> return part index
|
||||
"""
|
||||
ipn_test = 'PART-000000-AA'
|
||||
pk = 1
|
||||
|
||||
def test_ipn_match(index_result=False, detail_result=False):
|
||||
index_redirect = False
|
||||
detail_redirect = False
|
||||
|
||||
response = self.client.get(reverse('part-detail-from-ipn', args=(ipn_test,)))
|
||||
|
||||
# Check for PartIndex redirect
|
||||
try:
|
||||
if response.url == '/part/':
|
||||
index_redirect = True
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
# Check for PartDetail redirect
|
||||
try:
|
||||
if response.context['part'].pk == pk:
|
||||
detail_redirect = True
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
self.assertEqual(index_result, index_redirect)
|
||||
self.assertEqual(detail_result, detail_redirect)
|
||||
|
||||
# Test no match
|
||||
test_ipn_match(index_result=True, detail_result=False)
|
||||
|
||||
# Test unique match
|
||||
part = Part.objects.get(pk=pk)
|
||||
part.IPN = ipn_test
|
||||
part.save()
|
||||
|
||||
test_ipn_match(index_result=False, detail_result=True)
|
||||
|
||||
# Test multiple matches
|
||||
part = Part.objects.get(pk=pk + 1)
|
||||
part.IPN = ipn_test
|
||||
part.save()
|
||||
|
||||
test_ipn_match(index_result=True, detail_result=False)
|
||||
|
||||
def test_bom_download(self):
|
||||
""" Test downloading a BOM for a valid part """
|
||||
|
||||
|
@ -99,7 +99,7 @@ part_urls = [
|
||||
# Export data for multiple parts
|
||||
url(r'^export/', views.PartExport.as_view(), name='part-export'),
|
||||
|
||||
# Individual part
|
||||
# Individual part using pk
|
||||
url(r'^(?P<pk>\d+)/', include(part_detail_urls)),
|
||||
|
||||
# Part category
|
||||
@ -124,6 +124,9 @@ part_urls = [
|
||||
# Bom Items
|
||||
url(r'^bom/(?P<pk>\d+)/', include(part_bom_urls)),
|
||||
|
||||
# Individual part using IPN as slug
|
||||
url(r'^(?P<slug>[-\w]+)/', views.PartDetailFromIPN.as_view(), name='part-detail-from-ipn'),
|
||||
|
||||
# Top level part list (display top level parts and categories)
|
||||
url(r'^.*$', views.PartIndex.as_view(), name='part-index'),
|
||||
]
|
||||
|
@ -663,6 +663,43 @@ class PartDetail(DetailView):
|
||||
return context
|
||||
|
||||
|
||||
class PartDetailFromIPN(PartDetail):
|
||||
slug_field = 'IPN'
|
||||
slug_url_kwarg = 'slug'
|
||||
|
||||
def get_object(self):
|
||||
""" Return Part object which IPN field matches the slug value """
|
||||
queryset = self.get_queryset()
|
||||
# Get slug
|
||||
slug = self.kwargs.get(self.slug_url_kwarg)
|
||||
|
||||
if slug is not None:
|
||||
slug_field = self.get_slug_field()
|
||||
# Filter by the slug value
|
||||
queryset = queryset.filter(**{slug_field: slug})
|
||||
|
||||
try:
|
||||
# Get unique part from queryset
|
||||
part = queryset.get()
|
||||
# Return Part object
|
||||
return part
|
||||
except queryset.model.MultipleObjectsReturned:
|
||||
pass
|
||||
except queryset.model.DoesNotExist:
|
||||
pass
|
||||
|
||||
return None
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
""" Attempt to match slug to a Part, else redirect to PartIndex view """
|
||||
self.object = self.get_object()
|
||||
|
||||
if not self.object:
|
||||
return HttpResponseRedirect(reverse('part-index'))
|
||||
|
||||
return super(PartDetailFromIPN, self).get(request, *args, **kwargs)
|
||||
|
||||
|
||||
class PartQRCode(QRCodeView):
|
||||
""" View for displaying a QR code for a Part object """
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user