运行python manage.py tests时触发django.db.utils.IntegrityError: UNIQUE constraint failed: books_book.id错误的解决方法咨询
Hey there, let's break down why you're hitting this unique constraint error and fix it step by step:
1. 测试对象创建的位置错误
You created self.user and self.book directly at the root level of the BookViewTests class, instead of inside a setUp() method. In Django's TestCase, class-level code runs only once before all tests start, and these objects get persisted in the database without being automatically cleaned up. When other tests (or re-runs of the same test) try to create a Book with the same id, it triggers the unique constraint conflict.
Fix:
Move your object creation code into a setUp() method. This method runs before every test case, creating fresh objects each time, and Django automatically rolls back the database after each test to avoid leftover data:
class BookViewTests(TestCase): def setUp(self): # Runs before every test method to create fresh test data self.user = get_user_model().objects.create_user( username='test', email='test@gmail.com', city='city', state='state', password='secret', id_2='96540845', work='Wipro' ) self.book = Book.objects.create( title='How to Win Friends and Influence People', author='Dale Carnegie', genre='Self-help', owner=self.user, id='75777553', is_approved=False, available=False ) # Book detail view test def test_book_detail_view(self): self.client.login(username='test', password='secret') # Pass the id as a string (matches your SlugField type) resp = self.client.get(reverse('book_detail', kwargs={'book_id': '75777553'})) self.assertEqual(resp.status_code, 200) self.assertTemplateUsed(resp, 'book_detail.html')
2. Fixed primary key values cause conflicts
You're manually setting a fixed id value for your Book. If any other test class creates a Book with the same id, or you add more test methods to this class, you'll hit the same unique constraint error again.
Optimization:
Avoid hardcoding the id by generating a unique string each time. Use the uuid module to create a unique 8-character id:
import uuid class BookViewTests(TestCase): def setUp(self): self.user = get_user_model().objects.create_user( username='test', email='test@gmail.com', city='city', state='state', password='secret', id_2='96540845', work='Wipro' ) # Generate a unique 8-character id for each test book unique_book_id = str(uuid.uuid4())[:8] self.book = Book.objects.create( title='How to Win Friends and Influence People', author='Dale Carnegie', genre='Self-help', owner=self.user, id=unique_book_id, is_approved=False, available=False ) def test_book_detail_view(self): self.client.login(username='test', password='secret') # Use the dynamically generated id from self.book resp = self.client.get(reverse('book_detail', kwargs={'book_id': self.book.id})) self.assertEqual(resp.status_code, 200) self.assertTemplateUsed(resp, 'book_detail.html')
This ensures every test gets a unique Book id, eliminating the constraint conflict entirely.
3. URL parameter type mismatch
Your Book model's id is a SlugField (string type), but you were passing an integer 75777553 in the test. This could cause URL resolution issues or fail to find the Book object. Using the string value (or dynamic self.book.id) fixes this.
Final Check
After making these changes, re-run your tests with:
python manage.py test
Each test will now run in an isolated database environment, and you won't hit the unique constraint error anymore.
内容的提问来源于stack exchange,提问作者Jay

