我正在尝试编写用于创建销售数据的测试。但是不断得到KeyError:“内容”时运行python manage.py测试。
该测试旨在确保用户可以添加/创建销售数据及其详细信息(嵌套),并以此作为参考,以创建可写嵌套序列化程序
models.py
# abstract base table for transactions
class Base_transaction(models.Model):
is_paid_off = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
pass
class Meta:
abstract = True
# sales table to store surface level sales information
# consist of sales_id as pk, customer_name, sub_total, discount, user_id,
# total, is_paid_off, created_at, updated_at
class Sales(Base_transaction):
sales_id = models.BigAutoField(
primary_key=True,
unique=True
)
customer_name = models.CharField(max_length=25, blank=True)
customer_contact = models.CharField(max_length=13, blank=True)
user_id = models.ForeignKey(
User,
on_delete=models.PROTECT,
null=True,
db_column='user_id'
)
def __str__(self) -> str:
return f'{self.sales_id} at {self.created_at} | Lunas={self.is_paid_off}'
class Meta:
db_table = 'sales'
# sales_detail table store the detail of sales per sparepart
# consist of sales_detail_id as pk, quantity, individual_price, total_price
# sales_id
class Sales_detail(models.Model):
sales_detail_id = models.BigAutoField(
primary_key=True,
unique=True
)
quantity = models.PositiveSmallIntegerField()
is_grosir = models.BooleanField(default=False)
sales_id = models.ForeignKey(
Sales,
on_delete=models.CASCADE,
db_column='sales_id'
)
sparepart_id = models.ForeignKey(
'Sparepart',
on_delete=models.SET_NULL,
null=True,
db_column='supplier_id'
)
def __str__(self) -> str:
return f'{self.sales_id} - {self.sparepart_id}'
serializers.py
class SalesDetailSerializers(serializers.ModelSerializer):
sparepart = serializers.ReadOnlyField(source='sparepart_id.name')
class Meta:
model = Sales_detail
fields = ['sales_detail_id', 'sparepart', 'quantity', 'is_grosir']
class SalesSerializers(serializers.ModelSerializer):
content = SalesDetailSerializers(many=True, source='sales_detail_set')
class Meta:
model = Sales
fields = ['sales_id', 'customer_name', 'customer_contact', 'is_paid_off', 'content']
def create(self, validated_data):
details = validated_data.pop('content')
sales = Sales.objects.create(**validated_data)
for detail in details:
Sales_detail.objects.create(sales_id=sales, **detail)
return sales
test.py
class SalesAddTestCase(APITestCase):
sales_url = reverse('sales_add')
def setUp(self) -> None:
# Setting up sparepart data
for i in range(3):
Sparepart.objects.create(
name=f'random name{i}',
partnumber=f'0Y3AD-FY{i}',
quantity=50,
motor_type='random m',
sparepart_type='random s',
price=5400000,
grosir_price=5300000,
brand_id=None
)
self.spareparts = Sparepart.objects.all()
# Creating data that gonna be use as input
self.data = {
'customer_name': 'someone',
'customer_contact': '085634405602',
'is_paid_off': False,
'content': [
{
'sparepart': self.spareparts[1].sparepart_id,
'quantity': 1,
'is_grosir': False,
},
{
'sparepart': self.spareparts[0].sparepart_id,
'quantity': 30,
'is_grosir': True,
}
]
}
def test_user_successfully_add_sales(self) -> None:
"""
Ensure user can add new sales data with it's content
"""
response = self.client.post(self.sales_url, self.data, format='json')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(response.data['customer_name'], 'someone')
self.assertEqual(len(response.data['content']), 2)
我正在使用泛型的视图。CreateAPIView
预期的响应将与www.example.com相同self.data其中sparepart字段变为该sparepart的名称。下面的示例使用随机数据给予一些上下文
{
'customer_name': 'someone',
'customer_contact': '085456105311',
'is_paid_off': False,
'content': [
{
'sparepart': 'something1', # the name of sparepart 1
'quantity': 5,
'is_grosir': False,
},
{
'sparepart': 'something2', # the name of sparepart 2
'quantity': 3,
'is_grosir': False,
}]
}
我尝试将内容中的sparepart
更改为= self.spareparts[1]
,但现在给予 *type**error类型为Sparepart的对象不是JSON可序列化的 *,将其更改为self.spareparts[1].name
会给出与之前相同的KeyError(内容)。
我怀疑错误是因为sparepart字段是SalesDetailSerializer
中的readonlyfield
,然后我将其更改为charfield
,但仍然得到相同的KeyError
我真的很困惑是什么使这个错误首先发生。
1条答案
按热度按时间arknldoa1#
我发现了问题:
SalesDetailSerializers
中sparepart
域为只读,无法用于我用途SalesSerializers
上的content
字段使用参数源sales_detail_set
。我不知道为什么validated_data中的content
键字段变成了sales_detail_set
而不是content
。我的解决方案:
1.因为我已经编写了一个测试,以确保用户可以获得销售清单的详细信息,这需要
sparepart
字段来显示备件名称,我不能改变它。相反,我创建了另一个名为SalesDetailPostSerializers
和SalesPostSerializers
的序列化程序,就像这样。1.在
SalesPostSerializer
中更改结束日期
然后将www.example.com中
self.data
内的sparepart
密钥名称更改test.py为sparepart_id