首页 > 解决方案 > 是否有解决方法在 django rest 中使用 URL 中具有特殊字符的字符串作为主键?

问题描述

我想创建一个模型来存储设置:

# name: string
# value: string
# desccription
# Example:
{
 "name": "currency.symbol",
 "value": "€",
 "description": "String to be attached at the end of some purchased values"
}

所以我这样创建模型:

model.py

class Setting(models.Model):
    """Class to represent the global settings of the app that apply to all users."""

    name = models.CharField(primary_key=True, max_length=100)

    value = models.CharField(max_length=500, null=True)

    description = models.TextField(null=True)

    class Meta: # pylint: disable=too-few-public-methods
        """Class to represent metadata of the object."""
        ordering = ['pk']

    def __str__(self):
        """String for representing the Model object."""
        return str(self.name)

view.py

class SettingViewset(viewsets.ModelViewSet): # pylint: disable=too-many-ancestors
    """API Endpoint to return the list of settings"""
    queryset = Setting.objects.all()
    serializer_class = SettingSerializer
    pagination_class = None
    permission_classes = [IsAuthenticated, IsAdminUserOrReadOnly]

serializer.py

class SettingSerializer(serializers.ModelSerializer):
    """Serializer for Setting."""

    class Meta: # pylint: disable=too-few-public-methods
        """Class to represent metadata of the object."""
        model = Setting
        fields = '__all__'

这在像这样的设置下工作得很好themelanguage但是现在我虽然也想要一个结构,像currency.nameor并且由于使用此路径currency.symbol的点而出现 404 错误:.

<base_path>/api/v1/admin/setting/Theme/ # works
<base_path>/api/v1/admin/setting/currency.symbol/ # returns 404

我认为这无关紧要,因为我从卷曲中得到了同样的结果,但是我Angular在我有我的 FE 的地方尝试了这个并且没有任何区别:

      const url = this.hostname + '/api/v1/admin/setting/' + encodeURI(element.name) + '/';

是否可以选择继续使用名称作为主键而不必切换到新的自动增量 pk?

更新: urls.py

"""
Django urls config for the  app.
"""
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from rest_framework.authtoken.views import obtain_auth_token
from myapp import views

# Create a router and register our viewsets with it.
router = DefaultRouter()
# ...
router.register(r'admin/setting', views.SettingViewset)
# ...

urlpatterns = [
    path('auth/', views.AuthToken.as_view(), name='auth'),
    #...
    path('', include(router.urls)),
]

标签: pythonurldjango-rest-frameworkencoding

解决方案


我发现了!事实上,默认情况下,«路由器将匹配包含除斜杠和句点字符之外的任何字符的查找值。»。您所要做的就是使用适当的正则表达式值扩展此默认值:

class SettingViewset(viewsets.ModelViewSet):
    ...
    lookup_value_regex = '[\w.]+'  # it should be enough :)

您也可以在另一个 stackoverflow 问题中看到这一点。


推荐阅读