Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set form field default value without showing the field in django forms?

Tags:

python

django

I'm using a forms.ModelForm to set a model's attributes. For one of the attributes, I'd like to set a default value, and I want to handle it in the form, thus no default=value on the model attribute in the model class.

On the form, though, I don't want to show the user the value, not even a hidden value, therefore, I can't put the field in fields=(...) and because of that, I can't use the field.initial=value way of setting the default.

I could override validation or saving methods and squeeze a attribute setting in there, but this is not what I would prefer to do.

Are there any "proper" or more elegant ways of solving this problem?

like image 614
Derek Avatar asked Dec 15 '22 04:12

Derek


2 Answers

Firstly, exclude the private field from the model form.

class MyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel
        exclude = ["private_field"]

Usually, if I wanted to use a different default value than in the model definition, I would set it in the view.

if form.is_valid():
    my_model = form.save(commit=False)
    my_model.private_field = "default value"
    my_model.save()

If you don't want to set the value in the view, I would suggest overriding the clean method and doing it there. It's not clear to me why you don't want to do this, or what would be more 'proper' about a different approach.

class MyModelForm(forms.ModelForm):
    def clean(self):
        self.instance.private_field = "default value"
        return super(MyModelForm, self).clean()

    class Meta:
        model = MyModel
        exclude = ["private_field"]
like image 185
Alasdair Avatar answered Apr 28 '23 15:04

Alasdair


You may not want to let the user set his own value to the form, so the best way to keep it like that is excluding the field, like this

class MyForm(forms.ModelForm);
    class Meta:
        model = MyModel
        exclude = [myfield]

and then in the view, lets assume is a Create,

class MyView(CreateView):
     model = MyModel
     form_class = MyForm
     def form_valid(self, form):
         # Save the validated data of your object
         self.object = form.save(commit = False)
         # Update the value of the desired field
         self.object.myfield = # Your value.
         # Save the object to commit the changes
         self.object.save()
         # Response with the success url or whatever is default
         return super(MyView, self).form_valid(form)

In this way you're done, and it's safe for you and for the user as you get full validation in your model.

like image 27
Oscar David Arbeláez Avatar answered Apr 28 '23 16:04

Oscar David Arbeláez