我正在建立一个电子商务,它有几个应用程序,如帐户、产品、类别、评论等。
我得到的错误输出是这样的:
django.db.utils.IntegrityError: insert or update on table "products_product" violates foreign key constraint "products_product_category_id_9b594869_fk_categories_category_id"
DETAIL: Key (category_id)=(3) is not present in table "categories_category".
当 Django 到达特定测试显示输出时,类别 ID 应该是 4,因为类别模型的其他三个实例是为之前的测试创建的。
只有我按特定顺序运行测试才能通过测试。
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=128)
brand = models.CharField(max_length=128)
image_url = models.CharField(default='',
max_length=512,
null=True,
blank=True)
description = models.CharField(max_length=512)
specifications = models.JSONField(null=True, blank=True)
price = models.DecimalField(max_digits=10, decimal_places=2)
vendor = models.ForeignKey('accounts.User',
on_delete=models.PROTECT,
related_name='products')
category = models.ForeignKey('categories.Category',
on_delete=models.PROTECT,
related_name='products',
blank=True,
null=True)
available = models.BooleanField(default=True)
class Meta:
unique_together = ['vendor', 'name']
def __str__(self) -> str:
return self.name
from django.test import TestCase
from products.models import Product
from products.tests.helpers import create_product
class SetUp(TestCase):
def setUp(self):
self.product = create_product()
return super().setUp()
class TesteProduct(SetUp):
def test_product(self):
self.assertEqual(
Product.objects.filter(pk=self.product.pk).exists(),
True,
)
retrieved_product = Product.objects.get(pk=self.product.pk)
self.assertEqual(
retrieved_product.name,
self.product.name,
)
self.assertEqual(
retrieved_product.brand,
self.product.brand,
)
self.assertEqual(
retrieved_product.description,
self.product.description,
)
self.assertEqual(
retrieved_product.specifications,
self.product.specifications,
)
self.assertEqual(
retrieved_product.category,
self.product.category,
)
products
应用程序的端点测试from json import dumps
from django.urls import reverse
from django.test import TestCase
from rest_framework import status
from rest_framework.request import Request
from rest_framework.test import APIRequestFactory, APIClient
from accounts.tests.helpers import UserTestMixin
from categories.tests.helpers import create_category
from products.models import Product
from products.tests.data import product_data
from products.tests.helpers import create_products_list
from products.api.serializers import ProductSerializer
class SetUpTestCase(UserTestMixin, TestCase):
def setUp(self):
self.category = create_category()
self.vendor = self.create_vendor()
product_data['vendor'] = self.vendor
product_data['specifications'] = dumps(
product_data['specifications']
)
product_data['category_id'] = self.category.pk
factory = APIRequestFactory()
self.request = Request(factory.get('/'))
self.client = APIClient()
self.client.force_authenticate(user=self.vendor)
return super().setUp()
class ProductListEndpointTestCase(SetUpTestCase):
def test_post(self):
response = self.client.post(reverse('products'),
data=product_data)
serializer = ProductSerializer(
Product.objects.get(pk=response.data['id']),
context={'request': self.request}
)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(response.data, serializer.data)
self.assertEqual(Product.objects.count(), 1)
def test_get(self):
create_products_list(self.vendor, self.category)
response = self.client.get(reverse('products'))
serializer = ProductSerializer(Product.objects.all(),
many=True,
context={'request': self.request})
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, serializer.data)
self.assertTrue(Product.objects.count() > 1)
from django.db import models
class Review(models.Model):
"""
Reviews require the order that the product was ordered in
Args:
- order (Order): The order that the product to review was was ordered in
- product (Product): The product to review
- user (User): The user that made the review
"""
order = models.ForeignKey('orders.Order',
on_delete=models.PROTECT,
related_name='reviews')
product = models.ForeignKey('products.Product',
on_delete=models.PROTECT,
related_name='reviews')
user = models.ForeignKey('accounts.User',
on_delete=models.PROTECT,
related_name='reviews')
title = models.CharField(max_length=64)
text = models.CharField(max_length=2048)
rating = models.IntegerField()
date = models.DateField(auto_now=True)
class Meta:
""" Users can only review a product once (per order) """
unique_together = ['order', 'product']
def __str__(self) -> str:
return self.text[:100]
from django.test import TestCase
from reviews.models import Review
from reviews.tests.helpers import create_review
class SetUpTestCase(TestCase):
def setUp(self):
self.review = create_review()
return super().setUp()
class TestReview(SetUpTestCase):
def test_review(self):
self.assertEqual(
Review.objects.filter(pk=self.review.pk).exists(),
True,
)
retrived_review = Review.objects.get(pk=self.review.pk)
self.assertEqual(
retrived_review.product,
self.review.product,
)
self.assertEqual(
retrived_review.user,
self.review.user,
)
self.assertEqual(
retrived_review.title,
self.review.title,
)
self.assertEqual(
retrived_review.text,
self.review.text,
)
self.assertEqual(
retrived_review.rating,
self.review.rating,
)
self.assertEqual(
retrived_review.date,
self.review.date,
)
from products.models import Product
from accounts.tests.helpers import UserTestMixin
from inventory.tests.helpers import create_inventory_item
from categories.tests.helpers import create_category
from products.tests.data import (
product_data, product_data_list
)
def create_product(vendor=None, category=None, data=product_data,
append_to_inventory=True):
data['vendor'] = vendor or UserTestMixin().create_vendor()
data['category'] = category or create_category()
product = Product.objects.create(**data)
if append_to_inventory:
add_product_to_inventory(product, quantity=10)
return product
def create_products_list(vendor=None, category=None, data=product_data_list):
return [
create_product(vendor, category, product_data) for product_data in data
]
def add_product_to_inventory(product, quantity=1):
return create_inventory_item(product, quantity)
from accounts.tests.helpers import UserTestMixin
from products.tests.helpers import create_product
from orders.tests.helpers import create_order, create_order_item
from reviews.models import Review
from reviews.tests.data import review_data
def create_review(user=None, product=None, review_data=review_data):
customer = user or UserTestMixin().create_customer()
order = create_order(user=customer)
product = product or create_product()
create_order_item(product=product, order=order)
return Review.objects.create(
user = customer,
order = order,
product = product,
**review_data,
)
注意:我知道有很多东西遗漏了,但请随意询问您是否需要有关该项目的更多信息。
我还有几个测试,但是同时运行这三个测试,导致了问题。
如果按此顺序运行测试...
python manage.py test reviews products
都通过了!
以默认顺序运行时...
python manage.py test products reviews
我收到之前提到的错误。
django.db.utils.IntegrityError: insert or update on table "products_product" violates foreign key constraint "products_product_category_id_9b594869_fk_categories_category_id"
DETAIL: Key (category_id)=(3) is not present in table "categories_category".
我确认模型上的所有更改都适用于数据库,我也在新数据库中尝试。
我以不同的顺序运行测试,显然,Django 尝试创建产品的类别的 ID 始终是实际 ID - 1.
我在一个用 pipenv 创建的 venv 中运行我的 Django 项目,还有其他包
我是初学者,我可能是错的我认为发生此错误是因为两个表都有关系。所以一个依赖于另一个所以依赖表列(带有forienkey)必须具有具有主键constaint
的表列的值