Django-如何铸造;无”;从url kwargs到None而不重复您自己

Django-如何铸造;无”;从url kwargs到None而不重复您自己,django,url,nonetype,Django,Url,Nonetype,我有一个这样的模型: #models.py class Location(BaseArticle): name = models.CharField(max_length=200) parent_location = models.ForeignKey("self", blank=True, null=

我有一个这样的模型:

#models.py
class Location(BaseArticle):
    name = models.CharField(max_length=200)
    parent_location = models.ForeignKey("self",
                                        blank=True,
                                        null=True,
                                        help_text="Fill in if this location is a smaller part of another location.",
                                        on_delete=models.SET_NULL)
    description = HTMLField(blank=True,
                            null=True,
                            help_text="A description of the location and important features about it")

    class Meta:
        unique_together = ('name', 'parent_location')
class LocationView(generics.APIView):
    parent = None
    ... rest of your code ...

class LocationViewWithparent(LocationView):
    parent = #Your code to get the parent_location_name parameter
我决定在我的URL中通过每个位置自己的名称及其父元素的名称来唯一地标识每个位置

# urls.py
urlpatterns = [
    path('locations/<str:parent_location_name>/<str:location_name>', wiki_views.LocationView.as_view(), name='location'),
]

# example url to location "Seedy Bar" located in "City"
# https://<DOMAIN>/locations/city/seedy bar
# example url to location "City" that does not have a parent_location
# https://<DOMAIN>/locations/none/city
#url.py
URL模式=[
路径('locations/',wiki_views.LocationView.as_view(),name='location'),
]
#位于“城市”的位置“破旧酒吧”的url示例
# https:///locations/city/seedy 酒吧
#指向没有父位置的位置“城市”的url示例
# https:///locations/none/city
从示例中可以看出,
parent\u location
为空/无的位置是可能的。我决定将这些URL的
None
转换为
“None”
,尽管我不确定
None
转换为什么。现在,您可能意识到,这意味着每当我对位置执行任何操作时,我都需要注意根据需要将视图中的
“None”
转换为
None
,这会很快变得烦人

我一直在想,处理这个问题最好的办法是什么,或者我是不是把自己设计成了一个角落

编辑:我认为最好的解决方案可能是在位置模型或其管理器中。在那里修复它意味着对所有视图和查询都处理此逻辑,而在视图级别解决此问题意味着需要对每个可能对位置进行“无”查询的视图实现此解决方案

到目前为止我想到了什么:

考虑到管理者是您与模型交互的界面,我检查了他们是否有任何东西,并无意中修改了get_queryset。然而,由于我自己并没有调用get_queryset,我不确定像filter/exclude这样的函数是否真的调用了其他我可能不知道的函数。然而,我通常最喜欢这种方法,因为它保持了关于如何使用模型/管理器处理这些东西的逻辑,这在我看来是属于它的


另一种选择当然是编写我自己的Mixin来解决视图级别上的问题,但这意味着我仍然需要记住每次这是一个问题。

我将如何做到这一点:

创建两个URL:

path('locations/<str:location_name>', wiki_views.LocationView.as_view(), name='location'),
path('locations/<str:parent_location_name>/<str:location_name>', wiki_views.LocationViewWithParent.as_view(), name='location'),

第二个视图将执行与父视图相同的操作,但会覆盖父变量

,多亏了@Aayus Agrawal的建议,我才勉强避免了这方面的错误做法。事后看来,我同意,在这方面使用经理不是一个好主意,因为虽然这可能会奏效,但它也会混淆输入,并在将来产生意想不到的结果

因此,我选择了Mixin解决方案,并实现了以下功能:

# settings.py
NONE_STRING = 'None'



# views.py
from django.conf import settings

class ReplaceNoneMixin(object):
    """Mixin to deal with URL Parameters that represent None. This mixin takes the name of a url parameter and assumes
    that if it represents None that it has the value of settings.NONE_STRING. If the parameter is encountered with that
    value, the value is changed from NONE_STRING to None."""
    kwargs: dict
    noneable_parameters_keys: list

    def setup(self, request, *args, **kwargs):
        """Changes the value of all url parameters specified in noneable_parameters_keys list. If the parameter has the
         settings.NONE_STRING value in kwargs then the value is set to None."""
        super().setup(request, *args, **kwargs)
        if isinstance(self.noneable_parameters_keys, str):
            self.noneable_parameters_keys = [self.noneable_parameters_keys]

        for parameter in self.noneable_parameters_keys:
            if parameter in self.kwargs and self.kwargs[parameter] == settings.NONE_STRING:
                self.kwargs[parameter] = None

@PhilippDoerner这是对您关于URL和视图的问题的回答。如果要使用多个视图,则应为所有视图使用类似的解决方案。继承比乱七八糟的if/else更好,并且可以保持代码可读性和易于修改。如果您的问题范围与您发布的问题明显不同,您应该保留旧问题,并在StackOverflow上创建一个新问题,因为您发布的问题将持续很长时间,并帮助其他人获得答复!(很抱歉删除了之前的评论,我意识到我的表述是错误的,因此重写了此评论,希望比您的回复更快)。您还让我意识到,我忘了提到还有多个其他视图依赖于相同的模式(或其中一些模式)来获取位置。因此,这种方法主要将逻辑从视图中推到url中。当然更干净,但是当一个视图的新url也使用Locatin时,仍然需要记住位置的这种特殊行为。@PhilippDoerner注意:您所描述的是数据摄取问题,而不是数据库问题。在数据库层清理数据是非常糟糕的做法。从根本上说,进入应用程序的任何数据都必须首先清理,然后再进行处理。永远不要反过来。最好的方法是使用两个URL(这很有意义。两种不同格式的传入数据因此需要两个URL),但如果您无法做到这一点,则必须在视图中进行处理。在视图中有两种方法可以做到这一点:您可以创建一个Mixin并在所有视图中继承它,并将“none”设置为none。或者,您也可以使用序列化程序对DRF执行此操作。@PhilippDoerner在视图中执行此操作时有一个建议:无论您使用什么代码从kwargs获取父id,请将其替换为接受kwargs变量的函数,如果值为“None”,则将其替换为None。另外,如果您想了解为什么在数据库层这样做是不好的做法,您可以搜索“神奇字符串”以及它们如何经常造成很多麻烦