NoReverseError в среде разработки, но не в тесте
У меня есть представление - называемое 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'),
)
views.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.
Я позаботился о том, чтобы синхронизировать и перезапустить сервер разработки. Что вызвало бы такое различное поведение между средой тестирования и разработки? Я использую Django 1.5 на Mac OSX Lion.
1 ответ
Решение
Действительно глупая ошибка. Проблема была в регулярном выражении шаблона URL. r'^(?P<pk>\d)/checkout/$'
был только захват 1-значный ПК. Это было пропущено +
после \d
, Так и должно быть:
...
# ex: /devices/13/checkout
url(r'^(?P<pk>\d+)/checkout/$',
DeviceCheckout.as_view(),
name='checkout'),
...