0

I am fairly new to Django. Below is what I am trying to achieve

I am adding some fields on my form dynamically based on the models (configurable_product_options_model) that I get from view. My idea is to make use of these dynamically added fields to create an activation record (ActivationRecord (models.Model)). I am not able to get hold of these fields (none of which map to the data fields inside my model [well obviously]) inside the clean function of my model ActivationRecord to create some entry that gets saved in the database.

View

def activation_record(request):

    configurable_product_options_modeltouse = None 
    product_options_modeltouse = None

    if request.session['feature_name'] == "M-Vault" :
        product_options_modeltouse = MLink_Product_Options
        configurable_product_options_modeltouse = MLink_Configurable_Product_Options

    # if this is a POST request we need to process the form data
    if request.method == 'POST':
        # create a form instance and populate it with data from the request:

        feature = request.session['feature_name']

        form = ActivationRecordForm (request.POST, product_options_model = product_options_modeltouse, 
                                     configurable_product_options_model = configurable_product_options_modeltouse)
        # check whether it's valid:
        if form.is_valid():
            # process the data in form.cleaned_data as required
            # redirect to a new URL: 
            form.save()
            return redirect('/admin/sales_portal/activationrequest/')

    # if a GET (or any other method) we'll create a blank form
    else:

        form = ActivationRecordForm(initial={'feature_name' : request.session['feature_name'],
                                             'customer_reference' : request.session['customer_reference'],
                                             'host_method'  : request.session['host_method'],
                                             'host_id'      : request.session['host_id'],
                                             'activation_type' : request.session['activation_type']}, 
                                             product_options_model = product_options_modeltouse,
                                             configurable_product_options_model = configurable_product_options_modeltouse)

        # Disabled the populatd fieds in the ISODE activation record form
        form.fields['host_id'].widget.attrs['readonly'] = True

    return render(request, 'sales_portal/activation_record.html', {'form': form})

Form

class ActivationRecordForm (ModelForm) :

def __init__(self, *args, **kwargs) :

    # Populate product options from the model based on the feature in the activation request

    product_options_model = kwargs.pop('product_options_model')
    configurable_product_options_model = kwargs.pop('configurable_product_options_model')

    super(ActivationRecordForm, self).__init__(*args, **kwargs)

    # Add product options in the form
    if product_options_model :
        self.fields['sub_feature'] = forms.ModelMultipleChoiceField(label='Product Options ', 
                                           required=False, 
                                           queryset = product_options_model.objects.all())

    # Add configurable product options in the form
    if configurable_product_options_model : 
        queryset = configurable_product_options_model.objects.all()
        for configurable_product_options in queryset :
            name = "%s " % configurable_product_options
            self.fields[name] = forms.CharField(required=False, 
                                           widget=forms.TextInput(attrs={'id':'CONFIGURABLE_PRODUCT_OPTION'}))

Inside the clean function of ActivationRecord model, I want to make use of the data filled in these dynamically added fields ("%s " % configurable_product_options). I am trying to figure it out myself (I am sure there must be a very easy way to do this, but if someone could give me a hint, I will be thankful). Tried get_fields() but it does not list the dynamically added fields on the form.

class ActivationRecord (models.Model) :
    def clean (self) :
    fields = self._meta.get_fields() 
ktime
  • 63
  • 13
  • Could this be the way https://stackoverflow.com/questions/17126983/add-data-to-modelform-object-before-saving – ktime Jan 17 '20 at 10:59

1 Answers1

0

I realized that the right way to do this (perhaps) is not in the Model but in my view. Idea is to get hold of the model object without saving the form (commit=False) and then modifying it based on the configurable parameters before saving again.

if request.method == 'POST':

    feature = request.session['feature_name']

    form = ActivationRecordForm (request.POST, product_options_model = product_options_modeltouse, 
                                 configurable_product_options_model = configurable_product_options_modeltouse)

    # check whether it's valid:
    if form.is_valid():

        queryset = configurable_product_options_modeltouse.objects.all()

        product_options = []

        for configurable_product_options in queryset :
            if form.cleaned_data["%s " % configurable_product_options] :
                val = str(configurable_product_options) # Get the label
                val = val.replace(" ", "") # Remove spaces from the label
                val = val.lower() # Make the label lowercase
                val = val+"="+str(form.cleaned_data["%s " % configurable_product_options])  
                product_options.append(val)

        # modify the activation record with the configurable product options before 
        # saving the form and redirecting to a new URL: 
        if product_options :
           activation_record_object = form.save(commit=False)
           activation_record_object.sub_feature = str(activation_record_object.sub_feature)+ "," + ",".join(product_options)

        form.save()
ktime
  • 63
  • 13