0

我有一个视图 - 下面称为 DevicesListView - 在测试环境(在 Webtest 中)中执行没有问题,但是当我尝试在开发环境中执行相同的视图时,我收到 NoReverseMatch 错误。

设备/urls.py

from inventory.devices.views import DeviceCheckout
urlpatterns = patterns('',
    # NOTE: these are namespaced as 'devices'

    # ex: /devices
    url(r'^$', 
        DevicesListView.as_view(),
        name='index'),

    # ex: /devices/3/checkout
    url(r'^(?P<pk>\d)/checkout/$',
        DeviceCheckout.as_view(),
        name='checkout'),
)

视图.py

class DevicesListView(ListView):
    '''Index view for devices.'''
    model = Device
    template_name = 'devices/index.html'
    context_object_name = 'all_devices'
    def get(self, request):
        #  ... 
    def post(self, request):
        """Process the action for the selected devices.
        """
        action = request.POST['action']  # the selected action
        # Get the IDs of the devices that had their checkboxes selected
        selected_pks = [int(v) for v in request.POST.getlist('device_select')]
        # Get the selected Device objects
        selected_devices = Device.objects.filter(pk__in=selected_pks)
        # ... Logic to handle selected action ...
        # redirect to lendee selection page
        device = selected_devices[0]
        if action == 'checkout_selected':
            return redirect('devices:checkout', pk=device.pk)  # throws NoReverseMatch in development
        elif action == 'checkin_selected':
            return redirect('devices:checkin', pk=device.pk)
        return redirect('devices:index')

webtest_tests.py

from django_webtest import WebTest
from inventory.user.tests.factories import UserFactory
from inventory.devices.tests.factories import DeviceFactory
class TestAUser(WebTest):
    def setUp(self):
        self.user = UserFactory()

    def test_can_checkout_device(self):
        # two devices are already created
        DeviceFactory()
        DeviceFactory()
        # goes to devices page
        res = self.app.get('/devices', user=self.user)
        # checks the first device
        form = res.forms['device_control']
        form.set('device_select', True, index=0)
        # Selects Checkout device
        form.set('action', 'checkout_selected')
        # Submits form
        res = form.submit().follow()
        assert_equal(res.status_code, 200) # PASSES

设备/index.html

  <form method="post" id="device_control" action="">
    {% csrf_token %}
    <label><span class="action-label">Action:</span>
      <select name="action">
        <option value="" selected="selected">---------</option>
        <option value="checkout_selected">Checkout</option>
        <option value="checkin_selected">Checkin</option>
        <option value="delete_selected">Delete selected</option>
      </select>
    </label>
    <input type="submit" name="_save" class="default btn" value="Go"/>
  </div><!-- end btn-toolbar -->
  <table class='table table-striped'>
    <thead>
      <th>Select</th>
      <th>Name</th>
    </thead>
    <tbody>
    {% for device in all_devices %}
      <tr>   
        <td><input type="checkbox" value="{{ device.pk }}" name='device_select' id="select_device{{ device.pk }}"></td>
        <td>{{ device.name }}</td>
      </tr>
    {% endfor %}
    </tbody>
  </table>
</form>

我得到的模板错误是:

NoReverseMatch at /devices/
Reverse for 'checkout' with arguments '()' and keyword arguments '{'pk': 13}' not found.

我已确保同步数据库并重新启动开发服务器。什么会导致测试和开发环境之间出现这种不同的行为?我在 Mac OSX Lion 上使用 Django 1.5。

4

1 回答 1

0

确实是个愚蠢的错误。问题出在 url 模式正则表达式中。r'^(?P<pk>\d)/checkout/$'只捕获 1 位数的 pk。它缺少一个+after \d。所以应该是:

...
# ex: /devices/13/checkout
url(r'^(?P<pk>\d+)/checkout/$',
    DeviceCheckout.as_view(),
    name='checkout'),
...
于 2013-03-24T21:05:11.837 回答