在Django中获取外键关联的ClientType.name值问题求助
问题解决:通过外键获取关联模型字段并返回JSON
问题描述
需要通过Clients表的外键ID获取关联的ClientType.name值,传递给JsonResponse,但使用select_related后报错:AttributeError: 'str' object has no attribute '_meta'
原视图代码:
def patientdetails(request): patient_id = request.POST.get('patient') context = { 'company' : Clients.objects.filter(id=patient_id).select_related() } qs_json = serializers.serialize('json', context) return JsonResponse({'data': qs_json})
Models代码:
class ClientType(models.Model): name = models.CharField(max_length=128, blank=True, null=True) is_active = models.BooleanField(default=True) created_at = models.DateTimeField(blank=True, null=True, auto_now_add=True) updated_at = models.DateTimeField(blank=True, null=True, auto_now=True) class Meta: managed = True db_table = 'client_type' class Clients(models.Model): client_type = models.ForeignKey(ClientType, models.DO_NOTHING) first_name = models.CharField(max_length=128, blank=True, null=True) middle_name = models.CharField(max_length=128, blank=True, null=True) last_name = models.CharField(max_length=128, blank=True, null=True) birthdate = models.DateField(blank=True, null=True) sex = models.CharField(max_length=128, blank=True, null=True) address = models.CharField(max_length=128, blank=True, null=True) occupation = models.CharField(max_length=128, blank=True, null=True) class Meta: managed = True db_table = 'clients'
原前端处理代码:
}).done(function(data){ var resultdata = JSON.parse(data.data); });
错误原因
- serializers.serialize参数错误:
serializers.serialize()要求传入QuerySet或模型实例,而你传入的是字典context,这会导致序列化时识别错误,触发'str' object has no attribute '_meta'异常。 - select_related未指定关联字段:
select_related()没有明确指定要关联的外键字段(client_type),虽然不会直接报错,但会导致查询效率低下,且无法确保关联数据被正确加载。 - 返回数据格式冗余:直接序列化QuerySet再转JSON会生成嵌套结构,前端需要额外解析,且默认序列化不会包含外键关联的具体字段值。
解决方案
修改视图代码
直接构造包含关联字段的字典,避免使用serializers.serialize()的冗余处理,同时明确指定关联字段:
from django.http import JsonResponse from .models import Clients def patientdetails(request): patient_id = request.POST.get('patient') # 获取单个客户对象,预加载关联的client_type数据 client = Clients.objects.filter(id=patient_id).select_related('client_type').first() if not client: return JsonResponse({'data': None}) # 构造包含关联字段的响应数据 client_data = { 'id': client.id, 'first_name': client.first_name, 'middle_name': client.middle_name, 'last_name': client.last_name, 'birthdate': client.birthdate.strftime('%Y-%m-%d') if client.birthdate else None, 'sex': client.sex, 'address': client.address, 'occupation': client.occupation, 'client_type_name': client.client_type.name # 直接获取关联的ClientType名称 } return JsonResponse({'data': client_data})
修改前端处理代码
现在返回的data.data是直接的JSON对象,无需额外解析:
}).done(function(data){ var resultdata = data.data; // 直接使用关联字段,例如: // console.log(resultdata.client_type_name); });
关键修改点
- 使用
select_related('client_type')明确指定预加载的外键关联,减少数据库查询次数,提升性能。 - 用
.first()获取单个客户对象(符合patient_id对应唯一客户的场景),避免返回QuerySet带来的冗余。 - 手动构造响应字典,直接包含
client_type.name,让前端可以直接使用目标字段。 - 移除错误的
serializers.serialize()调用,避免参数类型不匹配的异常。
内容的提问来源于stack exchange,提问作者McLarvel
相关产品推荐
相关产品推荐

