Django不匹配URL,没有反向匹配

时间:2016-02-28 09:05:54

标签: python django

我使用基于TDD的方法来处理我的Django项目,这是一个自制材料数据库。我已经能够通过功能和单元测试添加一个跃点记录。我遇到的问题是更新视图功能(编辑现有记录)。我之前使用基于类的视图完成了这个操作并遇到了一些我无法回答的错误,这就是为什么我使用TDD /功能视图方法而不是直接进入CBV&#39 ; S

我目前收到以下错误,表示我的观看次数beerdb/edit/(?P<pk>\\d+)/hops/$没有反向匹配。所以我在我的Hop模型上创建了一个get_absolute_url方法:

def get_absolute_url(self):
    return reverse('updatehops', kwargs={'pk': self.id})

返回反向网址:

django.core.urlresolvers.NoReverseMatch: Reverse for 'updatehops' with arguments '()' and keyword arguments '{'pk': ''}' not found. 1 pattern(s) tried: ['beerdb/edit/(?P<pk>\\d+)/hops/$']

这是我的测试,结果是上面的错误:

    def test_can_update_hops(self):
        self.client.post(
            '/beerdb/add/hops/',
            data={
                'name': 'Warrior',
                'min_alpha_acid': 24.00,
                'max_alpha_acid': 32.00,
                'country': 'USA',
                'comments': 'Very bitter, not good for aroma'
            })

        hop_instance = Hop.objects.filter(name='Warrior')[0]
        response = self.client.get('/beerdb/edit/%d/hops/' % hop_instance.id)
        self.assertEqual(response.status_code, 200)

我的其他项目详情如下。任何人都可以指出我可能会出错的地方吗?我也认为我的urls.py可能需要一些修改。我无法弄清楚如何使用模板返回反转的网址。我查看了渲染,render_to_response,重定向和HttpResponseRedirect对象,但我不知道如何返回该上下文。在基于类的视图中,我会调用super方法并获取上下文数据,将主键添加到“动作”中,但我不知道如何在此处应用它。

项目详情

urls.py

urlpatterns = [
    url(r'^$', views.homebrewmain, name='beerdb_main'),
    url(r'^hops/$', views.hops, name='hops_list'),
    url(r'^add/hops/$', views.addhops, name='addhops'),
    url(r'^edit/(?P<pk>\d+)/hops/$', views.updatehops, name='updatehops')
]

models.py

class Hop(models.Model):

    name = models.CharField(max_length=200, default='')
    min_alpha_acid = models.DecimalField(max_digits=4, decimal_places=2)
    max_alpha_acid = models.DecimalField(max_digits=4, decimal_places=2)

    # Country codes for origin (as defined by http://countrycode.org)
    AUSTRALIA = 'AUS'
    CANADA = 'CAN'
    CHINA = 'CHN'
    CZECH_REPUBLIC = 'CZE'
    FRANCE = 'FRA'
    GERMANY = 'DEU'
    NEW_ZEALAND = 'NZL'
    POLAND = 'POL'
    UNITED_KINGDOM = 'GBR'
    UNITED_STATES = 'USA'

    COUNTRY_CODES = (
        (AUSTRALIA, 'Australia'),
        (CANADA, 'Canada'),
        (CHINA, 'China'),
        (CZECH_REPUBLIC, 'Czech Republic'),
        (FRANCE, 'France'),
        (GERMANY, 'Germany'),
        (NEW_ZEALAND, 'New Zealand'),
        (POLAND, 'Poland'),
        (UNITED_KINGDOM, 'United Kingdom'),
        (UNITED_STATES, 'United States'),
    )

    country = models.CharField(max_length=3,
                               choices=COUNTRY_CODES,
                               default=UNITED_STATES
                               )

    comments = models.TextField(default='')
    def get_absolute_url(self):
        return reverse('updatehops', kwargs={'pk': self.id})

编辑:我已更新了我的查看功能,以返回反向网址的重定向,而不使用点表示法:

def updatehops(request, pk):

    hop_record = Hop.objects.filter(pk=pk)[0]
    edit_form = HopForm(request.POST or None, instance=hop_record)

    if request.method == 'POST':
        if edit_form.is_valid():
            edit_form.save()
            success_url = reverse('hops_list')
        return HttpResponseRedirect(success_url)
    hop_form_url = reverse('updatehops', kwargs={'pk': hop_record.id})
    return redirect(hop_form_url)

正如我在下面的评论中所指出的,如果我在响应= 302上断言status_code,则会通过测试,但我需要200才能确保我获得渲染的表单,以便我可以访问响应,更改一些数据并在我稍后编写其余测试时重新保存。

更新:我在做了一些研究之后修改了网址,以便现在传递给hop_id而不是<pk>

url(r'^edit/(?P<pk>\d+)/hops/$', views.updatehops, name='updatehops'),

我仍然收到错误,但是它收到了错误消息中的pk:

django.core.urlresolvers.NoReverseMatch: Reverse for 'updatehops' with arguments '()' and keyword arguments '{'pk': 7}' not found. 1 pattern(s) tried: ['beerdb/edit/(?P<hop_id>\\d+)/hops/$']

编辑2:我已经添加了&#39; pk&#39;返回URL,添加追溯

回溯

Template error:
In template /Path/To/Site/Site/homebrewdatabase/templates/homebrewdatabase/hops.html, error at line 23
   Reverse for 'updatehops' with arguments '()' and keyword arguments '{'pk': ''}' not found. 1 pattern(s) tried: ['beerdb/edit/(?P<pk>\\d+)/hops/$']   
   13 :         {% include 'homebrewdatabase/addhops.html' %}
   14 : 
   15 :         <!--Modal data begins here to edit hops-->
   16 :         <div class="modal fade" id="updatehops" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
   17 :             <div class="modal-dialog" role="document">
   18 :                <div class="modal-content">
   19 :                    <div class="modal-header">
   20 :                        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
   21 :                        <h4 class="modal-title" id="myModalLabel">Add Hops</h4>
   22 :               </div>
   23 :               <form action=" {% url 'homebrewdatabase:updatehops' pk=hop.id %} " method="POST">
   24 :                 <div class="modal-body">
   25 :                     {{ form.as_p }}
   26 :                     {%  csrf_token %}
   27 :                 </div>
   28 :               <div class="modal-footer">
   29 :                 <button type="button" id="close" class="btn btn-default" data-dismiss="modal">Close</button>
   30 :                 <button type="submit" id="submit" class="btn btn-primary">Submit</button>
   31 :               </form>
   32 :               </div>
   33 :             </div>

修改3: views.pyhops.html

3 个答案:

答案 0 :(得分:1)

如果您希望测试客户端遵循重定向,请使用follow=True

response = self.client.post(
        '/beerdb/add/hops/',
        data={...}, 
        follow=True, 
   ) 

然后,您可以检查回复的内容。如果您想测试重定向,可以使用assertRedirects而不是检查状态代码。

以下是关于撤消网址的一些提示。首先,使用网址格式名称,例如updatehops,而不是视图的完整路径'homebrewdatabase.views.updatehop'。其次,确保你的kwargs匹配。您在网址中有hop_id。因此你需要

reverse('updatehops', kwargs={'hop_id': hop_record.id})

答案 1 :(得分:0)

response = self.client.get('/beerdb/edit/%d/hops/' % hop_instance.id)

在上面的测试代码行中,不应该将上面的行作为beerdb_main而不仅仅是beerdb。

仅供参考:我指的是您的代码的测试部分。

答案 2 :(得分:-1)

你必须这样做: reverse('updatehops')

检查https://docs.djangoproject.com/en/1.9/ref/urlresolvers/