Установите значение поля в методе Django Form clean (), если это поле не передано в конструктор - PullRequest
5 голосов
/ 03 ноября 2010

Мне нужно установить значение поля, а не передать конструктору Django Form.

У меня есть модель и форма, подобная этой:

class Message(models.Model):
    created     = models.DateTimeField()
    text        = models.CharField(max_length=200, blank=True, null=True)
    active      = models.BooleanField(default=False)

class MessageForm(forms.ModelForm):
    class Meta:
        model   = Message
        exclude = ('created', 'active')

    def clean(self):
        # check if user is blocked
        if user.is_admin():
            self.cleaned_data['active'] = True
        return self.cleaned_data

Ожидается : если текущий пользовательis admin - мне нужно автоматически установить сообщение как активное.Пользователь не должен передавать этот параметр в форме.

Actual : я вижу, что сохраненное сообщение всегда имеет флаг "False" (я могу удалить условие, и в этом случае я также вижу, что сообщение неactive).

Пожалуйста, помогите мне понять, как мне установить этот флаг " active " в методе clean () .

Ответы [ 3 ]

4 голосов
/ 03 ноября 2010

Предыдущий ответ сработает, но мне нравится инкапсулировать все внутренние операции формы, например, что показывать, а что нет, внутри формы. Я знаю, что вы упомянули, что не хотите отправлять значение поля конструктору, но если вы не возражаете против отправки пользователя, ваше решение будет работать. т. е. ваш конструктор:

def __init__(self, user):
    self.user = user
    super(BaseForm, self).__init__()

тогда в вашей чистоте вы просто меняете user на self.user. Есть еще одно дополнительное преимущество в этом. Скажем, завтра вы хотите назначить больше полей в зависимости от вашего пользователя, вам не нужно ничего добавлять к представлениям, вы можете просто добавить это к форме.

EDIT: Когда вы добавляете поле для исключения, оно не доступно в очищенных данных. Вместо этого установите его виджет как скрытый.

active = forms.BooleanField(widget=forms.HiddenInput)

РЕДАКТИРОВАТЬ 2: Если вы действительно не хотите, чтобы поле в форме В этом случае, вместо переопределения очистки, почему бы вам не переопределить сохранение?

def save (self):
    super(BaseForm, self).save()
    if user.is_admin():
        self.instance.active=True
    super(BaseForm, self).save()
3 голосов
/ 03 ноября 2010

Не делайте этого в методе clean () формы, делайте это в представлении.

def your_view(request):
    if request.method == 'POST':
        form = MessageForm(data=request.POST)
        if form.is_valid():
            new_message = form.save(commit=False)
            if user.is_admin():
                new_message.active = True

Однако, если вы также хотите обработать случай, когда ваш пользователь not Администратор, используя ту же форму, вы можете посмотреть на включение аналогичной логики в форму init () вместо представления, возможно, передав информацию о пользователе из представления в init () формы ()

1 голос
/ 04 ноября 2010

Используйте это:

def message_form_factory(user):
    class MessageForm(forms.ModelForm):
        def clean(self):
            # check if user is blocked
            if user.is_admin():
                self.cleaned_data['active'] = True
            return self.cleaned_data
    return MessageForm

А по вашему мнению используйте:

form = message_form_factory(request.user)()
form = message_form_factory(request.user)(request.POST)
...