I am working on a DRF viewset which has a custom query (using annotate to group data), for this I want to implement list, retrive and delete functions based on a field called "batch" which contains a string with special characters like "-" and ".". I am able to make the viewset to list and retrive data but the data retrival fails when special characters (".") are present in the batch string. How can I setup viewset router to allow "." in the batch name?
class BatchViewSet(viewsets.ModelViewSet):
queryset = Product.objects.values('batch', 'customer', 'order_number').annotate(
total_quantity=Sum('total_quantity'),
ready_quantity=Sum('ready_quantity')
).filter(deleted_at__isnull=True).all()
serializer_class = BatchSerializer
lookup_field = 'batch'
filter_backends = [filters.SearchFilter, filters.OrderingFilter]
search_fields = ['batch', 'customer', 'order_number']
ordering_fields = ['batch', 'customer', 'order_number',
'total_quantity', 'ready_quantity']
ordering = ['batch']
def create(self, request, *args, **kwargs):
raise MethodNotAllowed('POST')
router.register(r'batches', BatchViewSet, basename="batches")
These are the routes generated to get the batch details
products/ ^batches/(?P<batch>[^/.]+)/$ [name='batches-detail']
products/ ^batches/(?P<batch>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='batches-detail']
which is not working on my batch TEATECH.01427964.11.08
but working on TEATECH
.
I tried making a custom router to get the batch number but it is also not working and I can't create a regex which can process the batch. Similarly I can't setup lookup_field_regex to catch the batch string.
I can navigate my batch retrival by using the batch name inside the search products/batches?search=TEATECH.01427964.11.08
like this, but it is a hacky solution and will not work with delete batch function, so how should I handle it?
Added re_path in the path of viewsets to receive characters such as TEATECH.01427964.11.08.
urls.py
from rest_framework.routers import DefaultRouter
from django.urls import re_path
from . import views
router = DefaultRouter()
batch_detail = views.BeeViewSet.as_view(
{"get": "retrieve", "patch": "partial_update", "delete": "destroy"})
router.register(r"batches", BatchViewSet, basename="batches")
urlpatterns = [
re_path(r"^products/batches/(?P<batch>[^/*]+)/$", batch_detail),
]
urlpatterns += router.urls
When you add the above route, the below request works.
GET --> products/batches/TEATECH.01427964.11.08/
The questioner asked for a query string form(products/batches?search=TEATECH.01427964.11.08), but '?' does not work as intended in django's re_path.
Maybe it's because it overlaps with the querystring, but it's not accurate.(If anyone knows anything about this, please comment)
It's awkward to remove only '?'(products/batches/search=TEATECH.01427964.11.08), so I made it in the basic formet provided by viewsets.
It's a lack answer, but I thought it could help as an alternative, so I answerd.