如何将复选框值保存到Django数据库中的Django数据库?

发布于 2025-01-21 20:44:09 字数 2347 浏览 1 评论 0原文

在Django Admin面板中,除flags subscriberplan模型的字段外,所有字段均保存到数据库中。也就是说,我可以(联合国)检查任何标志并尝试更新记录,但是标志状态不会保存到数据库中。

如果我运行python manage.py shell subscriberplan ,请执行此类操作

   plan = SubscriberPlan.objects.all()[0],
   plan.flags = "a"
   plan.save()

,然后数据库将被更新,并且活动>活动> Active flag将显示在管理面板,但是,仍然不可能从管理面板进行更新。

那么,在Django中,如何从管理面板中将这种字段保存到数据库中?老实说,我不明白为什么默认情况下没有保存它,而其他字段 保存。由于某些原因,看来管理面板不会以其形式传递检查标记值。

admin.py

from django.contrib import admin
from django.utils.safestring import mark_safe


class SubscriberPlanFlagsWidget(forms.Widget):
    available_flags = (
        ('a', ('Active')),
        ('n', ('New')),
        ('p', ('Popular')),

    def render(self, name, value, attrs=None, renderer=None):
        html = []
        for f in self.available_flags:
            html.append('<li><input type="checkbox" id="flag_%(key)s" %(checked)s key="%(key)s"/><label for="flag_%(key)s">%(name)s</label></li>' % {
                'key': f[0], 'name': f[1], 'checked': 'checked' if f[0] in value.lower() else ''})
        html = '<input type="hidden" name="%s" value="%s"/><ul class="checkbox flags">%s</ul>' % (name, value, ''.join(html))
        return mark_safe(html)


class SubscriberPlanAdmin(admin.ModelAdmin):
    def formfield_for_dbfield(self, db_field, **kwargs):
        if db_field.name == 'flags':
            kwargs['widget'] = SubscriberPlanFlagsWidget
        return super(SubscriberPlanAdmin, self).formfield_for_dbfield(db_field, **kwargs)

models.py

from django.db import models


class SubscriberPlan(models.Model):
    name = models.CharField(max_length=50, verbose_name=("Name"))
    price = models.DecimalField(max_digits=15, decimal_places=2,
                                verbose_name=("Price"))
    flags = models.CharField(max_length=30, verbose_name=("Flags"),
                             default='', blank=True)

    def _check_flag(self, name):
        return name in self.flags.lower()

    def active(self):
        return self._check_flag('a')

    def new(self):
        return self._check_flag('n')

    def popular(self):
        return self._check_flag('p')

In the Django admin panel, all fields are saved to the database, except for the flags field of the SubscriberPlan model. That is, I can (un)check any flag and try to thus update a record, but the flag statuses won't be saved to the database.

If I run python manage.py shell, import SubscriberPlan, do something like

   plan = SubscriberPlan.objects.all()[0],
   plan.flags = "a"
   plan.save()

then the database will be updated and the Active flag will be displayed in the Admin panel, but, still, it won't be possible to update it from the Admin panel.

So, how is it possible in Django to save this kind of a field to the database from the Admin panel? To be honest, I don't understand why it's not saved by default, while other fields are saved. It seems that the Admin panel, for some reason, doesn't pass the checkmark values in its form.

admin.py

from django.contrib import admin
from django.utils.safestring import mark_safe


class SubscriberPlanFlagsWidget(forms.Widget):
    available_flags = (
        ('a', ('Active')),
        ('n', ('New')),
        ('p', ('Popular')),

    def render(self, name, value, attrs=None, renderer=None):
        html = []
        for f in self.available_flags:
            html.append('<li><input type="checkbox" id="flag_%(key)s" %(checked)s key="%(key)s"/><label for="flag_%(key)s">%(name)s</label></li>' % {
                'key': f[0], 'name': f[1], 'checked': 'checked' if f[0] in value.lower() else ''})
        html = '<input type="hidden" name="%s" value="%s"/><ul class="checkbox flags">%s</ul>' % (name, value, ''.join(html))
        return mark_safe(html)


class SubscriberPlanAdmin(admin.ModelAdmin):
    def formfield_for_dbfield(self, db_field, **kwargs):
        if db_field.name == 'flags':
            kwargs['widget'] = SubscriberPlanFlagsWidget
        return super(SubscriberPlanAdmin, self).formfield_for_dbfield(db_field, **kwargs)

models.py

from django.db import models


class SubscriberPlan(models.Model):
    name = models.CharField(max_length=50, verbose_name=("Name"))
    price = models.DecimalField(max_digits=15, decimal_places=2,
                                verbose_name=("Price"))
    flags = models.CharField(max_length=30, verbose_name=("Flags"),
                             default='', blank=True)

    def _check_flag(self, name):
        return name in self.flags.lower()

    def active(self):
        return self._check_flag('a')

    def new(self):
        return self._check_flag('n')

    def popular(self):
        return self._check_flag('p')

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

飞烟轻若梦 2025-01-28 20:44:09

您的小部件的渲染方法将flags字段转换为表单上的复选框,但是当提交表单时,您需要转向另一个方向,然后将复选框转换为标志。小部件不知道如何自动执行此操作。从查看方法。尝试一下:

class SubscriberPlanFlagsWidget(forms.Widget):

    ...
    
    def value_from_datadict(self, data, files, name):
        value = ''
        for f in self.available_flags:
            if f[1] in data:
                value += f[0]
        return value

Your widget's render method translates the flags field into checkboxes on the form, but when the form is submitted you need to go the other direction, and translate the checkboxes back into flags. The widget doesn't know how to do that automatically. From looking at the django source code and the docs, you need to override the value_from_datadict method. Give this a try:

class SubscriberPlanFlagsWidget(forms.Widget):

    ...
    
    def value_from_datadict(self, data, files, name):
        value = ''
        for f in self.available_flags:
            if f[1] in data:
                value += f[0]
        return value
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文