Django:如何为`key:value`对制作一个表单?

时间:2015-08-07 14:48:54

标签: django django-forms

我有一个模型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之类的东西来完成此任务)来完成此操作工作?我一直在寻求解决方案好几天。

2 个答案:

答案 0 :(得分:2)

我的小解决方案。 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

此页面用于编辑/保存我们的标签。

<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>

答案 1 :(得分:1)

如果没有编写完整的新库,您似乎无法使用forms.Forms。你要求在运行时创建一个表单模型,这在我看来很难做到。

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