Metadata-Version: 2.4
Name: django-kv-config-widget
Version: 0.1.0
Summary: A Django widget for managing key-value configuration pairs with dynamic add/remove support
Author-email: rRR0VrFP <rrr0vrfp@qq.com>
Maintainer-email: rRR0VrFP <rrr0vrfp@qq.com>
License: MIT
Project-URL: homepage, https://gitee.com/rRR0VrFP/django-kv-config-widget
Keywords: django,widget,key-value,config,admin
Classifier: Development Status :: 5 - Production/Stable
Classifier: Framework :: Django
Classifier: Framework :: Django :: 4.2
Classifier: Framework :: Django :: 5.0
Classifier: Framework :: Django :: 5.1
Classifier: Framework :: Django :: 5.2
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: Django>=4.2
Requires-Dist: PyYAML>=6.0
Dynamic: license-file

# django-kv-config-widget

django-kv-config-widget 是一个专为 Django 后台设计的键值对（Key-Value）配置编辑组件。它提供表格化界面，帮助非技术用户直观管理 JSON 配置数据，有效避免手工编辑原始 JSON 可能引发的格式错误。

![Version](https://img.shields.io/badge/version-0.1.0-blue)
![Django](https://img.shields.io/badge/Django-4.2%20%7C%205.0%20%7C%205.1%20%7C%205.2-green)
![License](https://img.shields.io/badge/License-MIT-green)

## 特性

- 动态添加/删除行
- 多行值输入，自动撑高
- **类型系统** — `str`、`text`、`number`、`int`、`bool`（NullableBoolean）、`json`，自动切换控件，提交时校验类型
- **`default_keys`** — 预设键名，支持默认值、占位提示、类型
- **`required_keys`** — 必填键，值为空时阻止提交
- **`allow_custom`** — 设为 `False` 时键以下拉选择，不可重复，所有键用完后自动隐藏添加按钮
- **导入/导出** — 粘贴 YAML、JSON 或 `KEY=VALUE` 文本；一键导出为 YAML
- **Enter** 在键输入框跳转到值输入框；在值文本框内换行
- 国际化（默认英文，设置 `LANGUAGE_CODE=zh-hans` 切换中文）
- Null 安全，跟随 Django CSS 变量主题，系统焦点环
- 兼容 `JSONField` 和 `TextField`
- 纯 CSS，无外部依赖

## 安装

```bash
pip install django-kv-config-widget
```

在 `INSTALLED_APPS` 中注册：

```python
INSTALLED_APPS = [
    ...
    "django_kv_config_widget",
]
```

## 用法

### 推荐：使用 KVConfigFormField（自动校验）

```python
from django_kv_config_widget.fields import KVConfigFormField


class ConfigForm(forms.Form):
    settings = KVConfigFormField(
        label="应用配置",
        default_keys=[
            {"key": "DB_URL",         "type": "str",  "default": "postgres://localhost:5432/app", "placeholder": "数据库连接地址"},
            {"key": "DEBUG",          "type": "bool", "default": "true"},
            {"key": "PORT",           "type": "int",  "default": "8080"},
            {"key": "ALLOWED_HOSTS",  "type": "json", "placeholder": '["localhost", "example.com"]'},
            "LOG_LEVEL",
        ],
        required_keys=["DB_URL"],
        allow_custom=False,
        help_text="仅允许预定义的键，DB_URL 为必填项。",
    )
```

### 直接使用 Widget（手动校验）

```python
from django import forms
from django_kv_config_widget.widgets import DjangoKVConfigWidget


class ConfigForm(forms.Form):
    settings = forms.JSONField(
        widget=DjangoKVConfigWidget(
            default_keys=[
                {"key": "DB_URL", "type": "str", "default": "postgres://localhost/app"},
                {"key": "PORT",   "type": "int", "default": "8080"},
            ],
            required_keys=["DB_URL"],
        ),
    )

    def clean_settings(self):
        value = self.cleaned_data.get("settings") or {}
        widget = self.fields["settings"].widget
        DjangoKVConfigWidget.validate_required_keys(value, widget.required_keys)
        DjangoKVConfigWidget.validate_types(value, DjangoKVConfigWidget.get_type_map(widget.default_keys))
        if not widget.allow_custom:
            allowed = {dk["key"] for dk in widget.default_keys}
            for k in value:
                if k not in allowed:
                    raise forms.ValidationError("'%s' 不在预定义键中" % k)
        return value
```

### 在 Django Admin 中使用

```python
from django.contrib import admin
from django import forms
from django_kv_config_widget.fields import KVConfigFormField
from .models import MyModel


class MyModelForm(forms.ModelForm):
    config = KVConfigFormField(
        label="配置",
        default_keys=[{"key": "DB_URL", "type": "str", "default": "postgres://localhost/app"}],
        required_keys=["DB_URL"],
        allow_custom=False,
    )
    class Meta:
        model = MyModel
        fields = "__all__"


@admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
    form = MyModelForm
```

### `default_keys` 格式

| 形式 | 示例 | 效果 |
|------|------|------|
| `str` | `"LOG_LEVEL"` | 文本输入框，无默认值 |
| `dict` | `{"key":"PORT","type":"int","default":"8080","placeholder":"端口号"}` | 类型化输入，有默认值 + 占位提示 |

### 类型对照

| 类型 | 控件 | 值 |
|------|------|-----|
| `str` | textarea（单行外观） | 任意文本，支持换行 |
| `text` | textarea | 任意文本，支持换行 |
| `number` | `<input type="number">` | 浮点数 |
| `int` | `<input type="number" step="1">` | 整数 |
| `bool` | `<select>` | 空 / `true` / `false`（三态） |
| `json` | textarea | 合法 YAML/JSON |

### 导入 / 导出

点击 **Import** 粘贴 YAML、JSON 或 `KEY=VALUE` 文本，自动解析填充表格。  
点击 **Export** 将当前数据导出为 YAML。

### 国际化

默认界面为英文。设置以下内容可切换为中文：

```python
LANGUAGE_CODE = "zh-hans"
```

校验错误信息和占位提示均已翻译。

## API

### `DjangoKVConfigWidget`

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `default_keys` | `list[str \| dict]` | `[]` | 预定义键。`str` 为简单键名；`dict` 支持 `key`、`default`、`placeholder`、`type` |
| `required_keys` | `list[str]` | `[]` | 必填键列表，值为空时提交不通过 |
| `allow_custom` | `bool` | `True` | 是否允许自定义键。`False` 时键以下拉选择，不可重复，用完后隐藏添加按钮 |
| `attrs` | `dict` | `None` | 标准 Django widget HTML 属性 |

静态方法：
- `validate_required_keys(value, required_keys)` — 必填键为空时抛出 `ValidationError`
- `validate_types(value, type_map)` — 类型不匹配时抛出 `ValidationError`
- `get_type_map(default_keys)` → `dict` — 构建 `{键名: 类型}` 映射

### `KVConfigFormField(forms.JSONField)`

自动校验必填键、类型、自定义键限制。接收 `default_keys`、`required_keys`、`allow_custom` 参数（透传给内部 widget）。

## 数据格式

提交时以 JSON 对象形式存储。空键被丢弃。空提交返回 `""`。

```json
{"KEY1": "value1", "KEY2": "value2"}
```

## 开发

```bash
git clone ...
cd django-kv-config-widget
pip install -r requirements.txt
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver
```

- 管理后台：http://127.0.0.1:8000/admin/

## 更新记录

### v0.1.0

1. 动态添加/删除行，多行值自动撑高
2. `default_keys` 支持 dict 格式（`default`、`placeholder`、`type`）
3. 类型系统：`str`、`text`、`number`、`int`、`bool`（NullableBoolean）、`json`
4. `required_keys` — 必填键为空时阻止提交
5. `allow_custom` — 预定义键下拉选择；禁止重复；用完后隐藏添加按钮
6. `KVConfigFormField` — 内置必填 + 类型 + 自定义键校验
7. 导入/导出 — YAML、JSON、KEY=VALUE
8. 键盘：Enter 键→值跳转；Enter 值内换行
9. 国际化（英文默认，中文通过 `LANGUAGE_CODE=zh-hans`）
10. 系统焦点环、Django CSS 变量主题
11. `validate_required_keys`、`validate_types`、`get_type_map` 静态方法
