Flutter调用Django筛选API时遇类型转换异常求助
问题描述
基于本地Django Restful API开发Flutter应用,数据库存在嵌套的ShowsModel与DirectorModel。已在Django的views.py中实现通过check_director参数按导演ID筛选剧集的功能,API测试有效,但Flutter端调用时出现type 'String' is not a subtype of type 'int' of 'index'异常。目前能打印正确结果,但异常仍存在,求解决办法。
相关代码
JSON数据结构
[ { "id": 1, "name": "Shows name", "annotation": "Some long text", "image": "/media/images/poster.jpg", "director": { "id": 2, "name": "First name", "surname": "Last name", "image": "/media/images/portrait.jpg" } } ]
Django views.py代码
check_director = self.request.query_params.get('check_director', None) if check_director: queryset = queryset.filter(director=check_director) serializer = ShowsSerializer(queryset, many=True) return Response(serializer.data)
Flutter API请求代码
static Future<ShowsModel> getShowsByDirector({required String director}) async { try { var uri = Uri.parse( "http://10.0.2.2:8000/showapi?check_director=1", // 应替换为=$id ); var response = await http.get(uri); print("response ${jsonDecode(utf8.decode(response.bodyBytes))}"); var data = jsonDecode((utf8.decode(response.bodyBytes))); if (response.statusCode != 200) { throw data["message"]; } return ShowsModel.fromJson(data); } catch (error) { log("an error occured while getting show info $error"); throw error.toString(); } }
Flutter页面相关代码
class DirectorDetailPage extends StatefulWidget { const DirectorDetailPage({Key? key, required this.id}) : super(key: key); final String id; @override State<DirectorDetailPage> createState() => _DirectorDetailPageState(); } class _DirectorDetailPageState extends State<DirectorDetailPage> { DirectorModel? directorModel; ShowsModel? showsModel; Future<void> getDirectorInfo() async { directorModel = await APIHandler.getDirectorsById(id: widget.id); setState(() {}); } Future<void> getDirectorShows() async { showsModel = await APIHandler.getShowsByDirector(); setState(() {}); } @override void didChangeDependencies() { getDirectorInfo(); getDirectorShows(); super.didChangeDependencies(); } // 显示导演信息的Widget构建代码 // 本容器应显示数据库中的一个剧集名称 Container( margin: const EdgeInsets.only(bottom: 15.0), child: showsModel == null ? const Center( child: CircularProgressIndicator(), ) : Text(showsModel!.name), ),
问题原因及解决办法
1. API返回数组而非单个对象
API返回的是数组格式的JSON([]包裹),但Flutter代码尝试用ShowsModel.fromJson(data)将数组解析为单个ShowsModel对象,导致类型不匹配异常。
解决:
修改API请求方法的返回类型为列表,并遍历数组逐个解析:
static Future<List<ShowsModel>> getShowsByDirector({required String director}) async { try { var uri = Uri.parse( "http://10.0.2.2:8000/showapi?check_director=$director", // 传入导演ID参数 ); var response = await http.get(uri); print("response ${jsonDecode(utf8.decode(response.bodyBytes))}"); List data = jsonDecode(utf8.decode(response.bodyBytes)); if (response.statusCode != 200) { throw data["message"]; } return data.map((item) => ShowsModel.fromJson(item)).toList(); } catch (error) { log("an error occured while getting show info $error"); throw error.toString(); } }
2. 页面代码未适配数组数据
页面中showsModel为单个对象类型,无法接收API返回的列表数据。
解决:
- 修改页面变量类型:
List<ShowsModel>? showsModelList;
- 更新数据获取方法:
Future<void> getDirectorShows() async { showsModelList = await APIHandler.getShowsByDirector(director: widget.id); setState(() {}); }
- 修改展示逻辑(以显示第一个剧集为例):
Container( margin: const EdgeInsets.only(bottom: 15.0), child: showsModelList == null || showsModelList!.isEmpty ? const Center(child: CircularProgressIndicator()) : Text(showsModelList![0].name), ),
3. 未正确传递导演ID参数
原代码中API请求硬编码了check_director=1,且调用方法时未传入参数,导致请求逻辑错误。
解决:
调用getShowsByDirector时传入widget.id,如上述代码所示。
4. Django参数类型优化(可选)
Django的query_params.get返回字符串类型,而director外键对应int类型,显式转换更稳妥:
if check_director: queryset = queryset.filter(director=int(check_director))
内容的提问来源于stack exchange,提问作者amyhawks
相关产品推荐
相关产品推荐

