在Django中通过用户输入的点符号修改Python字典的实现方案
解决Django API中解析点符号输入并修改字典的问题
嘿,针对你在Django API里遇到的这两个问题,我给你梳理一下最优的解决方案,刚好之前做过类似的需求,应该能帮到你!
一、解析点符号格式的用户输入
首先,咱们得先把用户提交的表单数据(每行的键值对)拆分成可处理的结构。用户的输入有两种分隔符(等号和冒号),还有不同类型的值(字符串、数字、数组、嵌套字典),所以解析逻辑要覆盖这些情况:
步骤1:拆分每行的键和值
先把用户输入的每一行按分隔符(=或:)拆分,注意去除两边的空格,比如把ticket.subject = Hello World拆成键ticket.subject和值Hello World。
步骤2:解析值的类型
用户输入的值可能是多种类型,咱们可以用ast.literal_eval来安全解析(比eval安全,不会执行恶意代码),比如:
- 字符串:直接保留(注意如果值有空格,要确保拆分时不会截断)
- 数字:自动转成int/float
- 数组/嵌套字典:解析成Python列表/字典
示例解析代码
import ast def parse_user_input(input_text): parsed_data = {} lines = [line.strip() for line in input_text.split('\n') if line.strip()] for line in lines: # 兼容等号和冒号分隔 if '=' in line: key_part, value_part = line.split('=', 1) elif ':' in line: key_part, value_part = line.split(':', 1) else: continue # 跳过无效行 key = key_part.strip() value_str = value_part.strip() # 解析值的类型 try: value = ast.literal_eval(value_str) except (ValueError, SyntaxError): # 如果解析失败,当作普通字符串处理 value = value_str parsed_data[key] = value return parsed_data
测试一下你的输入:
user_input = """ ticket.subject = Hello World ticket.group_id = 12345678 ticket.collaborators = [123, 4567, 890] ticket.custom_fields: [{id: 32656147,value: "something"}] """ parsed = parse_user_input(user_input) # 输出会是: # { # 'ticket.subject': 'Hello World', # 'ticket.group_id': 12345678, # 'ticket.collaborators': [123, 4567, 890], # 'ticket.custom_fields': [{'id': 32656147, 'value': 'something'}] # }
二、修改原字典的值:实现SetDictValueFromUserInput类
接下来是修改原字典的逻辑,核心是根据点符号的键,逐层遍历原字典,找到对应的位置替换值。还要注意字段名映射的问题(比如用户输入的ticket.collaborators对应原字典的collaborator_ids),所以咱们可以在类里加入一个映射表来处理这种差异。
类的实现思路
- 接收三个参数:点符号键、新值、原字典
- 把点符号键拆分成层级列表(比如
ticket.subject拆成['ticket', 'subject']) - 遍历层级列表,逐层进入原字典,直到最后一层
- 替换对应位置的值(如果有字段映射,先替换键名)
示例类代码
class SetDictValueFromUserInput: # 定义字段映射:用户输入的键 -> 原字典的键 FIELD_MAPPING = { 'collaborators': 'collaborator_ids', # 可以添加更多映射 } def __init__(self, user_dot_notation, user_new_value, original_dict): self.user_key = user_dot_notation self.new_value = user_new_value self.original_dict = original_dict self._update_dict() def _update_dict(self): # 拆分点符号键为层级 key_parts = self.user_key.split('.') current_level = self.original_dict # 遍历除最后一个外的所有层级 for part in key_parts[:-1]: # 如果当前层级不存在该键,可根据需求抛出错误或创建(这里假设原字典结构是固定的) if part not in current_level: raise ValueError(f"Invalid key path: {self.user_key}") current_level = current_level[part] # 处理最后一个键,检查是否需要映射 final_key = key_parts[-1] if final_key in self.FIELD_MAPPING: final_key = self.FIELD_MAPPING[final_key] # 替换值(这里可以添加校验逻辑,比如检查值的类型是否符合原字典的要求) if final_key not in current_level: raise ValueError(f"Field {final_key} does not exist in the original dict") # 可选:校验新值的类型和原字典一致 original_type = type(current_level[final_key]) if not isinstance(self.new_value, original_type) and original_type is not type(None): # 处理特殊情况,比如原字典是int,用户输入的是字符串数字 try: self.new_value = original_type(self.new_value) except (ValueError, TypeError): raise TypeError(f"Expected type {original_type.__name__} for {final_key}, got {type(self.new_value).__name__}") current_level[final_key] = self.new_value
使用示例
假设你的原字典是:
myDict = { "ticket": { "subject": "some subject I want to change", "group_id": 99999, "collaborator_ids": [], "custom_fields": [{"id": 32656147, "value": None}] } }
然后调用类来修改:
# 修改subject SetDictValueFromUserInput("ticket.subject", "Hello World", myDict) # 修改group_id SetDictValueFromUserInput("ticket.group_id", 12345678, myDict) # 修改collaborators(自动映射到collaborator_ids) SetDictValueFromUserInput("ticket.collaborators", [123, 4567, 890], myDict) # 修改custom_fields SetDictValueFromUserInput("ticket.custom_fields", [{"id": 32656147, "value": "something"}], myDict) # 查看修改后的myDict print(myDict['ticket']['subject']) # 输出: Hello World print(myDict['ticket']['collaborator_ids']) # 输出: [123, 4567, 890]
额外优化建议
- 校验增强:可以在类里加入更多校验逻辑,比如检查
custom_fields里的id是否和原字典匹配,或者数组的元素类型是否正确。 - 批量处理:如果用户提交多个键值对,可以写一个批量处理的函数,遍历解析后的
parsed_data,逐个调用SetDictValueFromUserInput。 - Django集成:在Django的API视图里,你可以把用户提交的表单数据(比如
request.POST.get('input_text'))传给parse_user_input,然后批量更新原字典,最后返回处理后的结果或者保存到数据库。
内容的提问来源于stack exchange,提问作者Andrew Bowman
相关产品推荐
相关产品推荐

