0

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)

1 Answers1

2

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.

dani herrera
  • 48,760
  • 8
  • 117
  • 177
  • Using instance doesn't add icon_main_color, printing the instance returns a (None) – Stephen Milic Jan 24 '22 at 07:08
  • Hello @StephenMilic you can access form instance like this ``print(form.instance)`` – Ankit Tiwari Jan 24 '22 at 07:20
  • using 'form.instance' still returns none – Stephen Milic Jan 24 '22 at 07:22
  • You focused the question on how to save the field (_"'forms.is_valid()' doesn't save it"_ ), but, maybe, the issue is on how to calculate the value. Are you sure `icon_main_color is not None` is not none and has the right value? – dani herrera Jan 24 '22 at 07:32
  • @daniherrera yes, I just did a test print in the if to confirm it and `icon_main_color` returned `(80, 171, 241)` – Stephen Milic Jan 24 '22 at 07:35
  • nice, can you edit your Q to include `social_color` model field? (how this field is declared on your model) – dani herrera Jan 24 '22 at 07:38
  • Did it, it's just a charfield, it used to have a default value, but it was acting the same, also I tried with a mere string instead of `icon_main_color` and still nope – Stephen Milic Jan 24 '22 at 07:44
  • But why are you trying to store a tuple in a charfield? A charfield is not intended to store tuples, just to store strings. If you store a string, with my answer, t should to work as expected. – dani herrera Jan 24 '22 at 07:52
  • I tried to replace the tuple with a string and even converted the tuple to `str` but even tho I didn't saved anything. e.g. of what I did: `form.cleaned_data["social_color"] = "#3b91cb"` also if you got sugestions of a replacement for the charfield I'm interested – Stephen Milic Jan 24 '22 at 07:55
  • 1
    @daniherrera I managed to make it work using your method, so thanks – Stephen Milic Jan 24 '22 at 08:38