大家好,我在使用 django drf 的时候遇到了一个问题,找了一堆资料,暂时还没找到好的解决方法,希望有懂的兄弟可以给指点一下。非常感谢。
class ProjectStatusModels(models.Model):
name = models.CharField(max_length=150,verbose_name='状态名称',unique=True,db_index=True)
def __str__(self):
return self.name
class Meta:
verbose_name = '项目状态管理表'
ordering = ('-id',)
class ProjectModels(models.Model):
project_id = models.CharField(verbose_name='项目编号',max_length=120,unique=True,db_index=True)
name = models.CharField(verbose_name='项目名称',max_length=150)
customer_name = models.CharField(verbose_name='客户名称',max_length=150,null=True,blank=True)
evaluation = models.IntegerField(verbose_name='项目估价',null=True,blank=True)
start_date = models.DateField(verbose_name='项目开始日期',null=True,blank=True)
expiration_date = models.DateField(verbose_name='项目截止日期',null=True,blank=True)
sales_name = models.ForeignKey(EmployeeModels,on_delete=models.DO_NOTHING,verbose_name='销售经理',null=True,blank=True)
status = models.ForeignKey(ProjectStatusModels,on_delete=models.DO_NOTHING,verbose_name='状态',null=True,blank=True,db_index=True)
create_time = models.DateTimeField(verbose_name='发布时间', auto_now_add=True)
update_time = models.DateTimeField(verbose_name='修改时间', auto_now=True)
def __str__(self):
return self.name
class Meta:
verbose_name = '项目管理表'
ordering = ('-id',)
class ProjectJsonView(APIView):
def get(self,request,*args,**kwargs):
project_id = request.query_params.get('project_id')
if not project_id:
project_obj = project_models.ProjectModels.objects.all()
ser = admin_project_serializers.ProjectModelsSerializers(instance=project_obj,many=True)
else:
project_obj = project_models.ProjectModels.objects.filter(id=project_id).first()
ser = admin_project_serializers.ProjectModelsSerializers(instance=project_obj,many=False)
return Response({
'status_code':20000,
'code':0,
'data':ser.data
})
def post(self,request,*args,**kwargs):
# 新增项目
req = {
'status_code':20000,
'msg':'新增成功'
}
ser = admin_project_serializers.ProjectModelsSerializers(data = request.data)
if ser.is_valid():
ser.save()
else:
req['status_code'] = 50000
req['msg'] = str(ser.errors)
return Response(req)
def put(self,request,*args,**kwargs):
# 编辑现有项目
req = {
'status_code':20000,
'msg':'修改成功'
}
sid = request.data.get('id')
project_obj = project_models.ProjectModels.objects.filter(id=sid).first()
ser = admin_project_serializers.ProjectModelsSerializers(data=request.data,instance=project_obj)
if ser.is_valid():
print('ser.validated_data:',ser.validated_data)
ser.save()
else:
req['status_code'] = 50000
req['msg'] = str(ser.errors)
return Response(req)
def delete(self,request,*args,**kwargs):
project_id = request.data.get('project_id')
project_obj = project_models.ProjectModels.objects.filter(id=project_id).first()
project_obj.delete()
return Response({
'status_code':20000,
'msg':'删除成功'
})
class ProjectStatusModelsSerializers(serializers.ModelSerializer):
# 项目状态序列化器
class Meta:
model = project_models.ProjectStatusModels
fields = '__all__'
class ProjectModelsSerializers(serializers.ModelSerializer):
# 项目序列化器
class Meta:
model = project_models.ProjectModels
fields = '__all__'
depth = 1
在项目 查询的时候可以返回如下的字段
{
"status_code": 20000,
"code": 0,
"data": [
{
"id": 5,
"status": null,
"project_id": "asdasdasd",
"name": "123123123",
"customer_name": "Abcd",
"evaluation": null,
"start_date": null,
"expiration_date": null,
"create_time": "2021-04-04T23:17:58.433641",
"update_time": "2021-04-04T23:17:58.433666",
"sales_name": null
},
{
"id": 4,
"status": null,
"project_id": "sss03",
"name": "qweqqweasd",
"customer_name": "",
"evaluation": 10000,
"start_date": null,
"expiration_date": null,
"create_time": "2021-04-04T23:17:03.571699",
"update_time": "2021-04-04T23:17:03.571714",
"sales_name": null
},
{
"id": 3,
"status": null,
"project_id": "sss01",
"name": "asasas",
"customer_name": "",
"evaluation": null,
"start_date": null,
"expiration_date": null,
"create_time": "2021-04-04T23:15:31.134011",
"update_time": "2021-04-04T23:15:31.134029",
"sales_name": null
},
{
"id": 2,
"status": {
"id": 2,
"name": "End"
},
"project_id": "0002",
"name": "s0002",
"customer_name": "微创医疗 111",
"evaluation": 500,
"start_date": "2021-04-04",
"expiration_date": "2021-05-11",
"create_time": "2021-04-04T22:43:18.374238",
"update_time": "2021-04-05T11:39:18.852015",
"sales_name": {
"id": 5,
"code": "0003",
"name": "endpein",
"phone": "",
"birthday": "2021-04-02",
"age": 18,
"on_the_job": true,
"identity_card": "",
"work_id": "",
"work_id_date": null,
"work_id_expiry_date": null,
"dormitory_address": "",
"passport_id": "",
"passport_expiry_date": null,
"multiskill_expiry": null,
"csoc_expiry": null,
"multiskill_category": "[]",
"bank_details": "",
"email": "[email protected]",
"remarks": "哈哈哈",
"nationality": null
}
},
{
"id": 1,
"status": {
"id": 6,
"name": "asdasd"
},
"project_id": "0001",
"name": "s01 项目",
"customer_name": "微创医疗",
"evaluation": 1000,
"start_date": "2021-04-29",
"expiration_date": "2021-04-30",
"create_time": "2021-04-04T22:42:51.462897",
"update_time": "2021-04-05T14:34:03.122631",
"sales_name": null
}
]
}
但是前端传来的数据如下 ,这个数据是 request.data 输出的
<QueryDict: {'csrfmiddlewaretoken': ['ntdydSUNRztDKOKmDSST36oFnSokUFVJG0t9YLXXvQtm6hyYOPT3WHMRPahy6kz8'], 'id': ['1'], 'name': ['s01 项目'], 'project_id': ['0001'], 'customer_name': ['微创医疗'], 'evaluation': ['1000'], 'start_date': ['2021-04-29'], 'expiration_date': ['2021-04-30'], 'status': ['2'], 'sales_name': ['']}>
但是当 ser.is_valid() 在输入 validated_data 的时候 表中 status
、sales_name
这 2 个一对多的 ForeignKey 字段就没有了。输出变成了如下样式:
ser.validated_data: OrderedDict([('project_id', '0001'), ('name', 's01 项目'), ('customer_name', '微创医疗'), ('evaluation', 1000), ('start_date', datetime.date(2021, 4, 29)), ('expiration_date', datetime.date(2021, 4, 30))])
请问一下,各位高手应该如何修改和调整呢?
1
Zhuzhuchenyan 2021-04-05 16:49:52 +08:00 1
根据官方文档对于 nested serialization 的描述,详见 https://www.django-rest-framework.org/api-guide/serializers/#writing-create-methods-for-nested-representations
“If you're supporting writable nested representations you'll need to write .create() or .update() methods that handle saving multiple objects.” 所以光有 depth=1 是不够的,需要重写对应的`create`方法 正好有空,给你个最低限度能用的代码 ```python # models.py class Author(models.Model): name = models.CharField(max_length=128) def __str__(self): return self.name class Book(models.Model): name = models.CharField(max_length=128) author = models.ForeignKey(to=Author, related_name='books', on_delete=models.CASCADE) def __str__(self): return self.name # serializers.py class AuthorSerializer(serializers.ModelSerializer): class Meta: model = Author fields = '__all__' class BookSerializer(serializers.ModelSerializer): author = AuthorSerializer() class Meta: model = Book fields = '__all__' def create(self, validated_data): author_data = validated_data.pop('author') author = Author.objects.get(name=author_data['name']) return Book.objects.create(author=author, **validated_data) # viewset.py class BookViewSet(ModelViewSet): queryset = Book.objects.all() serializer_class = BookSerializer pagination_class = None http_method_names = ['get', 'post'] ``` ``` # 示例代码 curl curl --location --request POST '{root_url}/books/' \ --header 'Content-Type: application/json' \ --data-raw '{ "name": "Book 2", "author": { "name": "YYH" } }' ``` 需要注意的是即使 author 里面传递了 ID,这个 ID 也不会出现在 validated_data 中,这个算是 drf 的一个局限性。 环境: djangorestframework==3.12.2 Django==3.1.3 |
2
Zhuzhuchenyan 2021-04-05 16:52:07 +08:00
不好意思,不知道为啥没有出现 readme 排版,难道是我使用姿势错了,
代码缩进都不见了,凑合着看看吧,这个问题只要重新 create 方法一般都能解决 |
3
endpain OP @Zhuzhuchenyan 非常感谢,我在仔细看看。跪谢!
|