Django:如何为“键:值”对制作表格?

Django: How to make a form for `key: value` pairs?

我有一个模型 Label 用于保存出现在我网站中的字符串:

class Label(models.Model):
    key = models.CharField(max_length=32, primary_key=True)
    value = models.CharField(max_length=128,blank=True, default='')

我想制作一个表格来自定义这些字符串。看起来像这样:

Site Configuration
this_is_key: this_is_value_____________
site_title: ________________
site_subtitle: _________________
site_copyright_info: _________________
admin_email: _________________
admin_phone: _________________
[Save]

并且当任何键的值不存在时,Label.create()使用我们为此预定义的默认值。

现在,如何使用 forms.Formforms.ModelForm(或其他任何东西...我不确定是否使用 formset 之类的东西来完成此任务)完成这份工作?这几天一直在寻求解决方案。

您似乎无法在不编写整个新库的情况下使用 forms.Forms。您基本上要求在 运行 时间创建一个表单模型,我认为这将很难做到。

我的建议是只编写您自己的自定义表单 类 如果这是您想要采用的方法。但是,请注意,您想要包含的任何验证或其他功能都必须与每个标签一起存储在数据库中。因此,如果您希望给定标签最多包含 150 个字符,则必须将其与键和值一起存储,以便您可以在 运行 时间

执行自己的验证

我的小解决方案。 https://kuanyui.github.io/2015/08/10/django-key-value-pairs-model-and-form/

settings.py

settings.py 中定义您的标签:

LABELS = [
    # ('key', 'label in form', 'default value'),
    ('site_title'     , 'Site Title',     'Hello World!'),
    ('copyright_info' , 'Copyright Info', 'John Smith (c) 2015'),
    ('admin_email'    , 'Your E-mail',    '02 1234 5678'),
]

models.py

from django.conf import settings
from django.db import models

class Label(models.Model):
    key = models.CharField(max_length=32, primary_key=True)
    value = models.CharField(max_length=128,blank=True, default='')

    @classmethod
    def get_label(cls, key):

        """Get the value of a label via key.
        If not found, create one with the default value in
        settings.LABELS."""

        try:
            return cls.objects.get(key=key).value
        except:
            default_value = [x for x in settings.LABELS if x[0] == key][0]
            cls.objects.create(key=key, value=default_value)
            return default_value

forms.py

我们定义 save() 方法来将 request.POST 保存到我们的模型中。

from django import forms
from pages.models import Label
from django.conf import settings

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit, Layout, Div, Button, Fieldset, HTML

class LabelForm(forms.Form):    

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for key, label, default_value in settings.LABELS: # settings.LABELS
            self.fields[key] = forms.CharField(max_length=128)
            self.fields[key].label = label

            # get_or_create => (<Label: Label object>, False)
            labelObj, _ = Label.objects.get_or_create(
                key=key,
                defaults={'value': default_value})
            self.fields[key].initial = labelObj.value

        self.helper = FormHelper()
        self.helper.add_input(Submit('submit', 'Submit'))

    def save(self, POST):
        for key, _, _ in settings.LABELS:
            Label.objects.filter(key=key).update(value=POST[key])

views.py

from pages.models import Label
from pages.forms import LabelForm

class LabelSettings(FormView):

    template_name = "label_settings.html"
    form_class = LabelForm
    success_url = '.'   # whatever.

    def form_valid(self, form):
        super().form_valid(form)
        form.save(self.request.POST)   # pass POST dict to LabelForm.save()
        return HttpResponseRedirect(self.get_success_url())

label_settings.html

此页面用于 edit/save 我们的标签。

<form method="post" action="">
  {% crispy form %}
</form>

在模板中使用

templatetags/common_tags.py

from django import template
from pages.models import Label
register = template.Library()

@register.simple_tag
def label(key):
    return Label.get_label(key)

在模板中

{% load common_tags %}
<h1>{% label 'site_title' %}</h1>