Как сохранить флаги в базу данных Django из панели администратора?

В админпанели Django все поля сохраняются в БД, кроме поля flags модели SubscriberPlan. То есть я могу (не)проверить любой флаг и попытаться таким образом обновить запись, но статусы флагов не будут сохранены в базе данных.

Если я запускаю python manage.py shell, импортирую SubscriberPlan, делаю что-то вроде

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

тогда база данных будет обновлена и флаг Active будет отображаться в панели администратора, но, тем не менее, обновить ее из панели администратора будет невозможно.

Итак, как в 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')

Посмотрев исходный код и документы, я думаю, что value_from_datadict - это то, что вам нужно. Попробуйте это:

class SubscriberPlanFlagsWidget(forms.Widget):
# Your existing code
...
    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
Вернуться на верх