0

I have a model whose Primary Key is a TextField. This is a minimalistic reproduction of my issue:

Model:

class Filename(models.Model):
    path = models.TextField(primary_key=True)

Serializer:

class FilenameSerializer(ModelSerializer):
    class Meta:
        model = Filename
        fields = '__all__'

View:

class FilenameViewSet(ModelViewSet):
    queryset = Filename.objects.all()
    serializer_class = FilenameSerializer

I'm using a DefaultRouter for URLs. Here is the problem: If I sent {"path":"test"} with a POST /filename/ I can perfectly retrieve my object with GET /filename/test/ as you would expect. However, if I POST /filename/ something like {"path":"c:\\test"} I would expect either GET /filename/c%3A%5Ctest/ or GET /filename/c%3A%5C%5Ctest/ to be the proper way to get it, but none of those works. Does anybody knows what's going on?

Update: The webserver logs show Not Found: /filename/c:\test so it's being decoded properly at some moment. Maybe some URL regex issue?

lithiium
  • 647
  • 8
  • 25
  • I doubt is very relevant for this question in particular, but python=3.7, django=2.1.2 and djangorestframework=3.8.2 – lithiium Oct 12 '18 at 09:16
  • The `path` simply stores "`test"`, so the query `SELECT * FROM filename WHERE path = 'C:\\test'` fails, hence nothing is returned. For the database this is just a string, whether that string "happens" to be a filepath is irrelevant. – Willem Van Onsem Oct 12 '18 at 09:18
  • @WillemVanOnsem I'm of course creating the c:\test object. The second POST with the json data is in the question too :) – lithiium Oct 12 '18 at 09:22

3 Answers3

3

The issue was not with any URL encoded in general, but with the dot (%2E) in particular. The DefaultRouter() does not match the dots by default. This behavior can be modified setting the lookup_value_regex attribute in the ViewSet.

class FilenameViewSet(ModelViewSet):
    queryset = Filename.objects.all()
    serializer_class = FilenameSerializer
    lookup_value_regex = '[^/]+'
lithiium
  • 647
  • 8
  • 25
0

hey you have to define the lookupfield , you can overide the get_object change string format to a norma text

class FilenameViewSet(ModelViewSet):
   queryset = Filename.objects.all()
   serializer_class = FilenameSerializer
   lookup_field = 'path'

def get_object(self):
   try:
      from urllib import unquote
   except ImportError:
      from urllib.parse import unquote
  path = unquote(kwarhs['path'))
  return self.get_queryset.get(path=path)
aman kumar
  • 3,086
  • 1
  • 17
  • 24
0

if im getting your question correctly . you problem is with json format . On adding escape character \ before special characters would resolve your issue.

see this link below: How to escape special characters in building a JSON string?

Babak Abadkheir
  • 2,222
  • 1
  • 19
  • 46