如何将两个网址映射到一个视图?

How to map two urls to one view?

这是我的 class 来自 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:

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(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)

你可以做到

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

我认为写 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)

如果您愿意,可以将视图代码缩短为 2 行。

一种略有不同的方法是接受两个单独的参数,一个用于 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

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