【问题标题】:How to map two urls to one view?如何将两个网址映射到一个视图?
【发布时间】:2017-07-23 07:31:58
【问题描述】:

这是我在 models.py 中的课程:

class Person(models.Model):
    name = models.CharField(max_length=64)
    persnr = models.AutoField(primary_key=True)

这是我的看法:

def show_person(request, persnr):
    pers = get_object_or_404(Person, pk=persnr)
    context={'pers':pers}
    return render(request, 'company/person.html', context)

这是我的网址:

url(r'^show_person/(?P<persnr>\d+)', "company.views.show_person", name='show_person'),

如何使用这两个 url 获得相同的视图 (show_person):

server/show_person/(persnr)

server/show_person/(name)

【问题讨论】:

  • 是什么阻止您创建另一个捕获名称的 URL?当然,这不起作用,因为视图需要 PK,所以不清楚为什么您希望两个 URL 转到同一个视图。
  • 我试过了,但不知道如何用预期的 pk 修复错误
  • 我建议不要让两个相同的页面具有相同的 URL。你应该选择一个你喜欢的,然后重定向另一个。例如将show_person/123 转换为show_person/john-smith

标签: django django-urls


【解决方案1】:
url(r'^show_person/(?P<persnr>.*)', "company.views.show_person", name='show_person'),

def show_person(request, persnr):
    per = Person.objects.filter(Q(name=persnr)|Q(persnr=persnr)).all()
    context={'pers':pers}
    return render(request, 'company/person.html', context)

【讨论】:

    【解决方案2】:

    你可以的

    pers = get_object_or_404(Person, Q(name=persnr)|Q(persnr=persnr))
    

    【讨论】:

      【解决方案3】:

      我认为写2个URL映射到同一个视图函数会更清楚:

      url(r'^show_person/(?P<persnr_or_name>\d+)', "company.views.show_person", name='show_person'),
      url(r'^show_person/(?P<persnr_or_name>.*)', "company.views.show_person", name='show_person'),
      
      
      def show_person(request, persnr_or_name):
          if persnr_or_name.isdigit():
              pers = get_object_or_404(Person, pk=persnr_or_name)
          else:
              pers = get_object_or_404(Person, name=persnr_or_name)
          context={'pers':pers}
          return render(request, 'company/person.html', context)
      

      并且假设您不允许像大多数网站那样使用纯数字作为名称。

      但对我来说,我更喜欢:

      url(r'^show_person/(?P<persnr_or_name>\d+)', "company.views.show_person", name='show_person_by_pk'),
      url(r'^show_person/(?P<persnr_or_name>.*)', "company.views.show_person", name='show_person_by_name'),
      
      
      def show_person_by_pk(request, pk):
          pers = Person.objects.get_or_404(pk)
          context={'pers':pers}
          return render(request, 'company/person.html', context)
      
      def show_person_by_name(request, name):
          pers = get_object_or_404(Person, name=name)
          context={'pers':pers}
          return render(request, 'company/person.html', context)
      

      如果你愿意,view的代码可以缩短到2行。

      【讨论】:

      • 这里不需要两个网址。无论如何,您正在与isinstance 核对。 .* 足以满足您的 view
      • @itzmeontv 如果在 URL 模块中定义它们比在视图模块中定义它们会更清楚。这就是我在编程中一直喜欢的东西——声明比渐进更好。
      • 好。但是persnr_or_name 会期待这两者,因为您声明了这一点。所以在声明的意义上没有更多的否定。否则你应该分别做persnrname。另外(?P&lt;persnr_or_name&gt;\d+无论如何也不接受名字。
      • 这行不通;该参数将始终是一个字符串,即使它捕获的值是数字。您需要尝试将其转换为 int 并捕获错误。
      • @DanielRoseman 你是对的,我已经解决了这个问题。而你的答案和我想了想的一样。
      【解决方案4】:

      一种稍微不同的方法是接受两个单独的参数,一个用于 pk,一个用于名称:

      url(r'^show_person/(?P<persnr>\d+)', "company.views.show_person", name='show_person'),
      url(r'^show_person/(?P<name>\w+)', "company.views.show_person", name='show_person'),
      
      def show_person(request, persnr=None, name=None):
          if persnr is not None:
              pers = get_object_or_404(Person, pk=persnr)
          elif name is not None:
              pers = get_object_or_404(Person, name=name)
          else:
              raise Http404
      

      【讨论】:

      • 不理解这种方式。为什么要使用 IF 语句? :)
      • 或者:(?P&lt;pk&gt;\d+)def show_person(request, **kwargs): ... get_object_or_404(Person, **kwargs) :-)
      • @Marin url 端点(绿色)可以接受persnrname。如果它们包含persnr,则将执行 if 语句。如果它们包含name,则将执行 elif 语句。如果什么都不提供,会引发 Http404
      【解决方案5】:

      如果你不想使用动态 url,你可以使用 django-arg-path 库 https://pypi.org/project/django-arg-path/0.2/

      【讨论】:

        猜你喜欢
        • 2014-12-21
        • 2010-11-13
        • 1970-01-01
        • 2020-05-20
        • 2010-12-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多