具有多个pk值的django NoReverseMatch

时间:2013-09-03 23:05:02

标签: django django-templates foreign-keys primary-key django-urls

我已经构建了一个测试用例,用于在访问多个pk值时演示django url和基于类的视图的问题。

演示此问题的文件是addressbook/family/templates/family/family_detail.html,我已经注释了我的尝试。

我想从家庭详细信息页面链接到特定的人,但第一次评论的尝试提供了NoReverseMatch at /family/2/ . Reverse for 'person-detail' with arguments '(1,)' and keyword arguments '{}' not found. 1 pattern(s) tried: ['family/(?P<pk>\\d+)/person/(?P<pk>\\d+)/$']

第二次及其第三次评论尝试在服务器上旋转很长时间,然后最终给出error at /family/1/patient/1/ redefinition of group name 'pk' as group 2; was group 1

项目结构是:

addressbook/
           addressbook/
                      urls.py
           family/
                 models.py
                 urls.py
                 views.py
                 templates/family/
                                  family_detail.html
                                  family_form.html
                                  family_list.html
           person/
                  models.py
                  urls.py
                  views.py
                  templates/person/
                                   person_detail.html
                                   person_form.html

addressbook/addressbook/urls.py

from django.conf.urls import patterns, include, url

urlpatterns = patterns('',
                       url(r'^family/',include('family.urls',namespace='family')),
)

addresbook/family/models.py

from django.db import models

class Family(models.Model):
    lastname=models.CharField(max_length=100)

    def __str__(self):
        return self.lastname

addressbook/family/urls.py

from django.conf.urls import include, patterns, url

from .views import FamilyCreateView, FamilyDetailView, FamilyListView

urlpatterns=patterns('',
                     url(r'^$',FamilyListView.as_view(),name='family-list'),
                     url(r'^create/$',FamilyCreateView.as_view(),name='family-create'),
                     url(r'^(?P<pk>\d+)/$',FamilyDetailView.as_view(),name='family-detail'),
                     url(r'^(?P<pk>\d+)/person/',include('person.urls',namespace='person')),
)

addressbook/family/views.py

from django.views import generic
from django.core.urlresolvers import reverse

from .models import Family

class FamilyListView(generic.ListView):
    context_object_name='family_list'
    model=Family


class FamilyDetailView(generic.DetailView):
    context_object_name='family'
    model=Family


class FamilyCreateView(generic.CreateView):
    model=Family

    def get_success_url(self,**kwargs):
        return reverse('family-detail',kwargs={'pk':self.object.pk})

addressbook/family/templates/family/family_detail.html

{% extends "base.html" %}
{% block content %}
<h1>{{ family }}</h1>
<ul>
  {% for person in family.person_set.all %}
    <li>{{ person }}</li>
    {#<li><a href="{% url 'family:person:person-detail' person.pk %}">{{ person }}</a></li>#}
    {#<li><a href="{% url 'family:person:person-detail' person.family.pk person.pk %}">{{ person }}</a></li>#}
    {#<li><a href="{% url 'family:person:person-detail' pk=person.family.pk pk=person.pk %}">{{ person }}</a></li>#}
  {% endfor %}
</ul>
<br><br><br>
<p><a href="{% url 'family:person:person-create' family.pk %}">Add family member</a></p>
<p><a href="{% url 'family:family-list' %}">Return to family list</a><p>
{% endblock content %}

addressbook/family/templates/family/family_form.html

{% extends "base.html" %}
{% block content %}
<h1>Add/Update Family</h1>
<form method="POST">{% csrf_token %}
{{ form }}
<p><button type="submit">Save</button></p>
</form>
<br><br><br>
<p><a href="{% url 'family:family-list' %}">Return to family list</a></p>
{% endblock content %}

addressbook/family/templates/family/family_list.html

{% extends "base.html" %}
{% block content %}
{% for family in family_list %}
<ul>
  <li><a href="{% url 'family:family-detail' family.id %}">{{ family }}</a></li>
</ul>
{% endfor %}
<br><br><br>
<a href="{% url 'family:family-create' %}">Create new family</a>
{% endblock content %}

addressbook/person/models.py

from django.db import models
from family.models import Family

class Person(models.Model):
    family=models.ForeignKey(Family)
    firstname=models.CharField(max_length=100)

    def __str__(self):
        return self.firstname

addressbook/person/urls.py

from django.conf.urls import patterns, url

from .views import PersonCreateView, PersonDetailView

urlpatterns=patterns('',
                     url(r'^create/$', PersonCreateView.as_view(),name='person-create'),
                     url(r'^(?P<pk>\d+)/$',PersonDetailView.as_view(),name='person-detail'),
)

addressbook/person/views.py

from django.views import generic
from django.core.urlresolvers import reverse
from django.shortcuts import get_object_or_404
from .models import Person
from family.models import Family

class PersonDetailView(generic.DetailView):
    model=Person


class PersonCreateView(generic.CreateView):
    model=Person

    def get_initial(self):
        family=get_object_or_404(Family,pk=self.kwargs.get('pk'))
        return {'family':family,}

    def get_success_url(self,**kwargs):
        return reverse('family:family-detail',args=[self.kwargs['pk']])
        #return reverse('person-detail',kwargs={'pk':self.object.pk})

addressbook/person/templates/person/person_detail.html:

{% extends "base.html" %}
{% block content %}
  {{ person }} {{ person.family }}
  <br><br>
<p><a href="{% url 'family:family-detail' person.family.pk %}">Return to family: {{ person.family }}</a></p>
{% endblock content %}

addressbook/person/templates/person/person_form.html

{% extends "base.html" %}
{% block content %}
<h1>Add/Update Person</h1>
<form method="POST">{% csrf_token %}
{{ form }}
<p><button type="submit">Save</button></p>
</form>
<br><br><br>
{#<p><a href="{% url 'family:family-detail' family.pk %}">Return to family {{ family }}</a></p>#}
{% endblock content %}

1 个答案:

答案 0 :(得分:4)

您需要重新考虑您的网址。希望以下评论会有所帮助。

在您的家庭网址中

url(r'^(?P<pk>\d+)/person/',include('person.urls',namespace='person')),

然后在你的网址中你有

url(r'^(?P<pk>\d+)/$',PersonDetailView.as_view(),name='person-detail'),

这表示/family/<pk>/person/<pk>/形式的网址。这是无效的,因为您在同一模式中使用了两次命名参数pk。

如果您在网址格式中重命名其中一个主键,例如:

url(r'^(?P<person_pk>\d+)/$',PersonDetailView.as_view(),name='person-detail'),

然后您可以在PersonDetail视图中使用pk_url_kwarg选项。

class PersonDetailView(generic.DetailView):
    model=Person
    pk_url_kwarg = 'person_pk'

另请注意,上面的url中有两个参数,但是当您尝试反转模板中的url时,只提供一个参数。你在哪里

<a href="{% url 'family:person:person-detail' person.pk %}">{{ person }}</a>

你需要提供家庭PK和人pk:

<a href="{% url 'family:person:person-detail' family.pk person.pk %}">{{ person }}</a>