0

テスト環境 (Webtest) では問題なく実行されるビュー (以下で DevicesListView と呼ばれます) がありますが、開発環境で同じビューを実行しようとすると、NoReverseMatch エラーが発生します。

devices/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

devices/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.

syncdb を実行し、開発サーバーを再起動するようにしました。テスト環境と開発環境でこのように動作が異なる原因は何ですか? Mac OSX Lion で Django 1.5 を使用しています。

4

1 に答える 1

0

本当にばかげた間違い。問題は URL パターンの正規表現にありました。r'^(?P<pk>\d)/checkout/$'1 桁の pk のみをキャプチャしていました。+アフターがありませんでした\d。したがって、次のようになります。

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