Stephen Milic
Stephen Milic

Reputation: 81

Django forms hidden field value assignation with a var after 'forms.is_valid()' doesn't save it

I have a form with an hidden input called social_color where I want nothing in, I need this input to assign a value after validating the form content to use one of the field content to do stuff and then assign the results to the hidden input.

According to this answer: https://stackoverflow.com/a/813474/15352101

I can simply do :

if form.is_valid():
    form.cleaned_data['Email'] = GetEmailString()

but for me using :

form.cleaned_data["social_color"] = icon_main_color

icon_main_color is the results of the stuff I had to do, it's a tuple containing 3 values but when I check the created object with the form, the value of social_color is still empty.

EDIT:

concerned view

@method_decorator(ajax_required, name="get")
class SocialCreationView(View):
    ctx = {
        "form": SocialCreationForm(),
    }

    def get(self, request, *args, **kwargs):
        
        return render(request, "social_creation.html", self.ctx)

    def post(self, request, *args, **kwargs):
        payload = json.loads(request.body.decode())
        form = SocialCreationForm(payload)
        
        if form.is_valid():
            # Quick binds
            social_name = form.cleaned_data["social_name"]
            social_icon = form.cleaned_data["social_icon"]
            file_extention = None

            #blabla

            icon_main_color = get_colors(icon_save_path)[0]
            if icon_main_color is not None:

                form.cleaned_data["social_color"] = icon_main_color

            form.save()
            return redirect("/")

        self.ctx["form"] = form
        return render(request, "social_creation.html", self.ctx)

EDIT2:

SocialProfile model:

class SocialProfile(models.Model):
    social_name = models.CharField(default="Unnamed social profile", max_length=100)
    social_username = models.CharField(default="Unknow username", max_length=16)
    social_icon = models.CharField(default="path/to/social/icon", max_length=250)
    social_link = models.CharField(default="https://social.nepmia.fr/", max_length=100)
    social_color = models.CharField(max_length=10)

Upvotes: 0

Views: 679

Answers (1)

dani herrera
dani herrera

Reputation: 51705

The django way to accomplish this is using instance=form.save(commit=False):

def post(self, request, *args, **kwargs):
    payload = json.loads(request.body.decode())
    form = SocialCreationForm(payload)
    
    if form.is_valid():
        # Quick binds
        social_name = form.cleaned_data["social_name"]
        social_icon = form.cleaned_data["social_icon"]
       
        # blah blah ...

        icon_main_color = get_colors(icon_save_path)[0]

        instance=form.save(commit=False) #<--- HERE!!

        if icon_main_color is not None:
            instance.social_color = icon_main_color #<--- AND HERE!!
        
        instance.save() #<--- AND HERE!!

        return redirect("/")

Quoting Creating forms from models docs:

If you call save() with commit=False, then it will return an object that hasn’t yet been saved to the database. In this case, it’s up to you to call save() on the resulting model instance. This is useful if you want to do custom processing on the object before saving it, or if you want to use one of the specialized model saving options. commit is True by default.

Upvotes: 2

Related Questions