You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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),所以咱们可以在类里加入一个映射表来处理这种差异。

类的实现思路

  1. 接收三个参数:点符号键、新值、原字典
  2. 把点符号键拆分成层级列表(比如ticket.subject拆成['ticket', 'subject'])
  3. 遍历层级列表,逐层进入原字典,直到最后一层
  4. 替换对应位置的值(如果有字段映射,先替换键名)

示例类代码

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 03:48:30