带多对多字段的POST表单视图测试无法通过,寻求技术建议
Hey there! Let's work through why your test isn't passing when trying to add a second Menu object. Here are the most common issues to check, along with actionable fixes:
1. Validate Your POST Data
First, take a look at the created_date field in your POST data. If your Menu model uses auto_now_add=True for this field, you don't need to include it in your request—passing it manually might even trigger a validation error. Try removing that key:
data={ 'expiration_date': timezone.now() + timezone.timedelta(days=2), 'season': 'Spring 2018', 'items': ['1'] }
Also, confirm the items field is formatted correctly. If it's a many-to-many relationship, make sure an Item with ID 1 actually exists in your test database (you’ll need to create it in your test’s setUp() method if it doesn’t).
2. Check Your View’s POST Handling
If your view uses a ModelForm, it must validate the form before saving. A common oversight is skipping the is_valid() check, which means no new object gets created. Your view should look something like this:
def new_menu(request): if request.method == 'POST': form = MenuForm(request.POST) if form.is_valid(): form.save() return redirect('menu_list') # Redirect on success # Handle GET requests or invalid forms ...
If the form fails validation, no new Menu is created—so your count stays at 1 instead of 2.
3. Confirm Authentication Permissions
If your view uses @login_required or permission decorators, your test’s anonymous client can’t submit the form. Add a login step to your test setup:
def setUp(self): self.user = User.objects.create_user(username='testuser', password='testpass') self.client.login(username='testuser', password='testpass') # Create your initial Menu object here to ensure consistent starting state Menu.objects.create(season='Winter 2018', expiration_date=timezone.now()+timezone.timedelta(days=7))
4. Debug with Intermediate Checks
Add quick assertions to narrow down the problem:
def test_create_new_menu_view(self): # Confirm starting count is 1 initial_count = Menu.objects.count() self.assertEqual(initial_count, 1) response = self.client.post('/menu/new', data={ 'expiration_date': timezone.now() + timezone.timedelta(days=2), 'season': 'Spring 2018', 'items': ['1'] }) # Check for a successful redirect (302 means the form was processed) self.assertEqual(response.status_code, 302) # Print the current count to see what's happening print(f"Current Menu count: {Menu.objects.count()}") # Final assertion self.assertEqual(Menu.objects.count(), 2)
If the status code is 200 instead of 302, the form was invalid. You can print the errors directly to diagnose:
print(response.context['form'].errors)
5. Ensure Test Database Isolation
Django’s TestCase resets the database after each test. Don’t rely on data from your development database—create your initial Menu object in the test’s setUp() or directly in the test before making the POST request.
内容的提问来源于stack exchange,提问作者Chris

