如何使我的 urlpatterns 更智能,以避免模板中的繁琐代码?
How do I make my urlpatterns smarter, to avoid cumbersome code in my templates?
现在我已经定义了我的 URL,它们可以包含类别的不同组合(始终打开),attribute_slugs (1 and/or 2) 和 brand_slug,全部使用下面定义的 url 模式。
在我的 views.py 文件中,我确保每个 slug 都存在于相应的模型中,否则将抛出 404。我还确保属性具有特定的顺序,这样我就可以避免属性只是在 URL 中交换的相同页面。然后将上下文发送到模板。
在我的类别模板中,我实现了一个基于上下文的电子商务过滤器。例如,过滤器可以显示指向特定页面上产品所包含属性的链接。因此,如果您在页面上:/shoes/,则颜色过滤器具有选项:/shoes/green、/shoes/blue/、/shoes/black/ 等。此过滤器使用默认值 { % url % } 带有基于上下文的参数的模板标签。
它工作正常,但有一个问题。它基于模板中很多的逻辑语句,比较繁琐。比如有一个if语句,检查当前页面是否有0属性、1属性和2属性。我还对品牌进行了同样的检查,这意味着模板中有很多 if 语句(记住它们会成倍增加)。我必须这样做,因为我需要根据页面的上下文编写不同版本的 { % url % } 模板标签。具体来说,模板标签的参数是根据页面变化的。
例如,如果给定页面不包含任何属性,则任何属性的可点击 URL 必须是:{% url 'products:product_categories' slug=category.slug attribute_slug=属性值 %}。换句话说:只设置了第一个attribute_slug。
另一方面,如果页面已经有一个属性,则检查新属性和旧属性的顺序以确定哪个先出现,然后将新属性添加到 URL,像这样:{% url 'products:product_categories' slug=category.slug attribute_slug=ATTRIBUTEVALUE attribute_slug2=属性值2 %}.
现在,当我这样解释时,这似乎比较简单。但是有很多不同的情况使这变得更加麻烦,例如还要考虑 brand_slug,并考虑到我也有用于从 URL.[= 中删除特定属性或品牌的功能。 11=]
最后,我的问题是; 是否有更好的方法 url模板 URL 标签中的模式和动态参数?
我自己的一个想法是在 URL 模板标签中传递任意数量的参数(就像经典 pythonic 中的 **args 或 **kwargs)。这看起来类似于:{% url 'products:product_categories' *KWARGS %}。我真的还没有找到让它起作用的方法。
你能想到什么更聪明的东西吗?
在此先致谢,并致以最诚挚的问候。
# urls.py
urlpatterns = [
# Category + Attributes
re_path(r"^vk/(?P<slug>[\w-]+)/$", ProductCategoryListView.as_view(), name="product_categories"),
re_path(r"^vk/(?P<slug>[\w-]+)/(?P<attribute_slug>[\w-]+){1}/$", ProductCategoryListView.as_view(), name="product_categories"),
re_path(r"^vk/(?P<slug>[\w-]+)/(?P<attribute_slug>[\w-]+){1}/(?P<attribute_slug2>[\w-]+){1}/$", ProductCategoryListView.as_view(), name="product_categories"),
# Category + Brand + Attributes
re_path(r"^vk/(?P<slug>[\w-]+)/(?P<brand_slug>[\w-]+)/$", ProductCategoryListView.as_view(), name="product_categories"),
re_path(r"^vk/(?P<slug>[\w-]+)/(?P<brand_slug>[\w-]+)/(?P<attribute_slug>[\w-]+){1}/$", ProductCategoryListView.as_view(), name="product_categories"),
re_path(r"^vk/(?P<slug>[\w-]+)/(?P<brand_slug>[\w-]+)/(?P<attribute_slug>[\w-]+){1}/(?P<attribute_slug2>[\w-]+){1}/$", ProductCategoryListView.as_view(), name="product_categories"),
]
按照建议写下上述讨论。
无论出于何种原因,都排除了将参数作为带有查询字符串的 GET 参数传递的可能性。他们必须在 URL.
我的建议是只解析 URLconfig 中的常量参数。对于其他人,通过对它们可以具有和不可以具有的值施加语法限制,将它们汇总到一个字符串参数中。像 http://.../attr:attrval;brand:somebrand;category:one;...
这样的东西被解析为其他参数。
为了最大限度地减少此后的代码重复,可以为所有 class-based 将要使用此技术的视图编写通用代码 Mixin。 setup
方法的子类:
class OtherparamsMixin( object):
def setup(self, request, *args, **kwargs):
super().setup( request, *args, **kwargs)
self.otherparams = {}
if 'otherparams' in self.kwargs:
params = self.kwargs['otherparams'].split(';')
for p in params:
k, v = p.split(':',1)
self.otherparams[k] = v
然后使用此 Mixin 定义的任何视图都将 self.otyherparams
自动可用
class SomeView( OtherparamsMixin, CBVclass):
并且对于 commonly-used CBV 类 可以定义基础 类 包括 mixin:
class SiteFormView( OtherparamsMixin, FormView):
pass
class SiteListView( OtherparamsMixin, ListView):
pass
等然后使用这些代替标准 CBV。
对于重定向,注入一种将一组 otherparams
的字典表示转换回文本字符串的方法可能也很有用:
@staticmethod
def otherparam_str( otherparams):
p = []
for k,v in otherparams.items():
if ";" in v:
raise ValueError( f'Semicolon not permitted in an otherparams value, but found "{k}" with value "{v}" )
p.append( f"{k}:{v}" )
return p.join(";")
现在我已经定义了我的 URL,它们可以包含类别的不同组合(始终打开),attribute_slugs (1 and/or 2) 和 brand_slug,全部使用下面定义的 url 模式。
在我的 views.py 文件中,我确保每个 slug 都存在于相应的模型中,否则将抛出 404。我还确保属性具有特定的顺序,这样我就可以避免属性只是在 URL 中交换的相同页面。然后将上下文发送到模板。
在我的类别模板中,我实现了一个基于上下文的电子商务过滤器。例如,过滤器可以显示指向特定页面上产品所包含属性的链接。因此,如果您在页面上:/shoes/,则颜色过滤器具有选项:/shoes/green、/shoes/blue/、/shoes/black/ 等。此过滤器使用默认值 { % url % } 带有基于上下文的参数的模板标签。
它工作正常,但有一个问题。它基于模板中很多的逻辑语句,比较繁琐。比如有一个if语句,检查当前页面是否有0属性、1属性和2属性。我还对品牌进行了同样的检查,这意味着模板中有很多 if 语句(记住它们会成倍增加)。我必须这样做,因为我需要根据页面的上下文编写不同版本的 { % url % } 模板标签。具体来说,模板标签的参数是根据页面变化的。
例如,如果给定页面不包含任何属性,则任何属性的可点击 URL 必须是:{% url 'products:product_categories' slug=category.slug attribute_slug=属性值 %}。换句话说:只设置了第一个attribute_slug。
另一方面,如果页面已经有一个属性,则检查新属性和旧属性的顺序以确定哪个先出现,然后将新属性添加到 URL,像这样:{% url 'products:product_categories' slug=category.slug attribute_slug=ATTRIBUTEVALUE attribute_slug2=属性值2 %}.
现在,当我这样解释时,这似乎比较简单。但是有很多不同的情况使这变得更加麻烦,例如还要考虑 brand_slug,并考虑到我也有用于从 URL.[= 中删除特定属性或品牌的功能。 11=]
最后,我的问题是; 是否有更好的方法 url模板 URL 标签中的模式和动态参数?
我自己的一个想法是在 URL 模板标签中传递任意数量的参数(就像经典 pythonic 中的 **args 或 **kwargs)。这看起来类似于:{% url 'products:product_categories' *KWARGS %}。我真的还没有找到让它起作用的方法。
你能想到什么更聪明的东西吗?
在此先致谢,并致以最诚挚的问候。
# urls.py
urlpatterns = [
# Category + Attributes
re_path(r"^vk/(?P<slug>[\w-]+)/$", ProductCategoryListView.as_view(), name="product_categories"),
re_path(r"^vk/(?P<slug>[\w-]+)/(?P<attribute_slug>[\w-]+){1}/$", ProductCategoryListView.as_view(), name="product_categories"),
re_path(r"^vk/(?P<slug>[\w-]+)/(?P<attribute_slug>[\w-]+){1}/(?P<attribute_slug2>[\w-]+){1}/$", ProductCategoryListView.as_view(), name="product_categories"),
# Category + Brand + Attributes
re_path(r"^vk/(?P<slug>[\w-]+)/(?P<brand_slug>[\w-]+)/$", ProductCategoryListView.as_view(), name="product_categories"),
re_path(r"^vk/(?P<slug>[\w-]+)/(?P<brand_slug>[\w-]+)/(?P<attribute_slug>[\w-]+){1}/$", ProductCategoryListView.as_view(), name="product_categories"),
re_path(r"^vk/(?P<slug>[\w-]+)/(?P<brand_slug>[\w-]+)/(?P<attribute_slug>[\w-]+){1}/(?P<attribute_slug2>[\w-]+){1}/$", ProductCategoryListView.as_view(), name="product_categories"),
]
按照建议写下上述讨论。
无论出于何种原因,都排除了将参数作为带有查询字符串的 GET 参数传递的可能性。他们必须在 URL.
我的建议是只解析 URLconfig 中的常量参数。对于其他人,通过对它们可以具有和不可以具有的值施加语法限制,将它们汇总到一个字符串参数中。像 http://.../attr:attrval;brand:somebrand;category:one;...
这样的东西被解析为其他参数。
为了最大限度地减少此后的代码重复,可以为所有 class-based 将要使用此技术的视图编写通用代码 Mixin。 setup
方法的子类:
class OtherparamsMixin( object):
def setup(self, request, *args, **kwargs):
super().setup( request, *args, **kwargs)
self.otherparams = {}
if 'otherparams' in self.kwargs:
params = self.kwargs['otherparams'].split(';')
for p in params:
k, v = p.split(':',1)
self.otherparams[k] = v
然后使用此 Mixin 定义的任何视图都将 self.otyherparams
自动可用
class SomeView( OtherparamsMixin, CBVclass):
并且对于 commonly-used CBV 类 可以定义基础 类 包括 mixin:
class SiteFormView( OtherparamsMixin, FormView):
pass
class SiteListView( OtherparamsMixin, ListView):
pass
等然后使用这些代替标准 CBV。
对于重定向,注入一种将一组 otherparams
的字典表示转换回文本字符串的方法可能也很有用:
@staticmethod
def otherparam_str( otherparams):
p = []
for k,v in otherparams.items():
if ";" in v:
raise ValueError( f'Semicolon not permitted in an otherparams value, but found "{k}" with value "{v}" )
p.append( f"{k}:{v}" )
return p.join(";")