(feature) Add host config editing view
Add a staff-only Django form for editing operational host settings while keeping host identity stable. Support address, enablement, SSH/source overrides, include/exclude lists, rsync extra args, and retention settings using the same SQL-backed HostConfig model consumed by backup and scheduler flows. Parse newline-separated list fields into JSON lists, preserve nullable excludes_replace semantics, and cover rendering plus update behavior with view tests.
This commit is contained in:
@@ -2,10 +2,68 @@ from __future__ import annotations
|
||||
|
||||
from django import forms
|
||||
|
||||
from .models import ScheduleConfig
|
||||
from .models import HostConfig, ScheduleConfig
|
||||
from .scheduler import parse_cron_expr
|
||||
|
||||
|
||||
class NewlineListField(forms.CharField):
|
||||
widget = forms.Textarea
|
||||
|
||||
def __init__(self, *args, **kwargs) -> None:
|
||||
kwargs.setdefault("required", False)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def prepare_value(self, value):
|
||||
if isinstance(value, list):
|
||||
return "\n".join(str(item) for item in value)
|
||||
return value
|
||||
|
||||
def to_python(self, value) -> list[str]:
|
||||
if not value:
|
||||
return []
|
||||
if isinstance(value, list):
|
||||
return [str(item).strip() for item in value if str(item).strip()]
|
||||
return [line.strip() for line in str(value).splitlines() if line.strip()]
|
||||
|
||||
|
||||
class NullableNewlineListField(NewlineListField):
|
||||
def to_python(self, value) -> list[str] | None:
|
||||
parsed = super().to_python(value)
|
||||
return parsed or None
|
||||
|
||||
|
||||
class HostConfigForm(forms.ModelForm):
|
||||
includes = NewlineListField(help_text="One include path per line. Leave empty to include defaults.")
|
||||
excludes_add = NewlineListField(help_text="One additional exclude pattern per line.")
|
||||
excludes_replace = NullableNewlineListField(
|
||||
help_text="Optional. When set, replaces global excludes; one pattern per line."
|
||||
)
|
||||
rsync_extra_args = NewlineListField(help_text="One extra rsync argument per line.")
|
||||
|
||||
class Meta:
|
||||
model = HostConfig
|
||||
fields = (
|
||||
"address",
|
||||
"enabled",
|
||||
"ssh_user",
|
||||
"ssh_port",
|
||||
"source_root",
|
||||
"includes",
|
||||
"excludes_add",
|
||||
"excludes_replace",
|
||||
"rsync_extra_args",
|
||||
"retention_daily",
|
||||
"retention_weekly",
|
||||
"retention_monthly",
|
||||
"retention_yearly",
|
||||
)
|
||||
help_texts = {
|
||||
"ssh_user": "Leave empty to use the global SSH user.",
|
||||
"ssh_port": "Leave empty to use the global SSH port.",
|
||||
"source_root": "Leave empty to use the global default source root.",
|
||||
}
|
||||
|
||||
|
||||
class ScheduleConfigForm(forms.ModelForm):
|
||||
cron_expr = forms.CharField(
|
||||
label="Cron expression",
|
||||
|
||||
Reference in New Issue
Block a user