djk2 / django-popup-view-field

Field and widget can render bootstrap dialog window with content from django view.
MIT License
22 stars 6 forks source link

Not a bug, but I am asking if it is possible: pass another form field data value to the popup field view modal box #18

Open ImanoWilliams opened 4 years ago

ImanoWilliams commented 4 years ago

In form.py: I am passing the ID field to the PopupViewField instance.

class APReviewForm(Form):
 fields=['ID', 'Name', 'Rating' 'Reason']
def __init__(self, *args, **kwargs):
 super(APReviewForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.fields['ID'] = IntegerField()
self.fields['Name'] = CharField()
self.fields['Rating'] = ChoiceField(widget=Select(), choices=RATING_CHOICES)
self.fields['Reason'] = PopupViewField(
view_class=SelectionReasonPopUpView,
popup_dialog_title="Please select a reason for the Pattern",
callback_data={'my_id': self.fields['ID'].initial, 'other_param': 'xxx'},
required=True,
)

That goes in formset: APReviewFormSet = formset_factory(APReviewForm, extra=0)

In my view, I have: I am setting some initial data for the formset in the get_context_data method.

class OntoRecAPView(FormView):
    form_class = APReviewForm
    template_name = "RecSys/ontoRecAPView.html"

    def get_context_data(self, **kwargs):
        context = super(OntoRecAPView, self).get_context_data(**kwargs)
        if self.request.POST:
            context['formset'] = APReviewFormSet()
        else:
            #Todo: Get attack patterns
            #returnWebAttackResults()
            context['formset'] = APReviewFormSet(
                initial=[{'ID':1, 'Name':"Ap Name1",
                          },
                         {'ID': 2, 'Name': "Ap Name2",
                          },
                         {'ID': 3, 'Name': "Ap Name3",
                          }
                         ])
        return context

In my popups.py, I have: I want when the load button is press, the ID from the respective APReviewForm is passed to the SelectionReasonPopUpView (PopupViewField) as shown below. I do some processing based on the ID value before the popup is shown to the user.

class SelectionReasonPopUpView(TemplateView):
    template_name='popups/selectionReason.html'
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        my_id = self.request.GET.get("attackPattern_id")
       myFunc(my_id)
        context['myContext'] = myFunc(my_id)
        return context

This is variant of #5

ImanoWilliams commented 4 years ago

In order for me to get the initial data from each I had to do:

class APReviewForm(Form):
    fields=['attackPatternID', 'attackPatternName', 'attackPatternRating' 'selectionReason']

    def __init__(self, *args, **kwargs):
        super(APReviewForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.fields['ID'] = IntegerField()
        self.fields['Name'] = CharField()
        self.fields['Rating'] = ChoiceField(widget=Select(), choices=RATING_CHOICES)
        initial = kwargs.get('initial', {})
        if initial:
            id_value=initi
al['ID']
        else:
            id_value='None'
        self.fields['selectionReason'] = PopupViewField(
            view_class=SelectionReasonPopUpView,
            popup_dialog_title="Please select a reason for the Attack Pattern",
            callback_data={'my_id': ID, 'other_param': 'xxx'},
            required=True,
        )

Lines:

initial = kwargs.get('initial', {})
        if initial:
            id_value=initi
al['ID']
        else:
            id_value='None'

were use to get the initial data from a field.

djk2 commented 4 years ago

Hi. I will look on this probably in next nearly weekend. I'm not sure if this functionality can be realized using my lib.

djk2 commented 4 years ago

Can you add your code to my demo ( in new branch) or prepare your own mini demo for testing? Will be really helpful for me if I will have some working code (maybe in fork of my repo) + some scenario. It is not enough clearly for me what you want aim.

ImanoWilliams commented 4 years ago

Hi, The only thing I did was placing the following code in the init method of the form class I created in the forms.py. This will get the initial values for the forms based on the initial values set in the views.py. I used an if statement because the first dictionary item is empty.

initial = kwargs.get('initial', {}) if initial: id_value=initi al['ID'] else: id_value='None'

see the form class below.

class APReviewForm(Form):
    fields=['ID', 'Name', 'Rating' 'Reason']

    def __init__(self, *args, **kwargs):
        super(APReviewForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.fields['ID'] = IntegerField()
        self.fields['Name'] = CharField()
        self.fields['Rating'] = ChoiceField(widget=Select(), choices=RATING_CHOICES)
        initial = kwargs.get('initial', {})
        if initial:
            id_value=initi
al['ID']
        else:
            id_value='None'
        self.fields['selectionReason'] = PopupViewField(
            view_class=SelectionReasonPopUpView,
            popup_dialog_title="Please select a reason for the Attack Pattern",
            callback_data={'my_id': ID, 'other_param': 'xxx'},
            required=True,
        )
APReviewFormSet = formset_factory(APReviewForm, extra=0)

In my views.py, I have the following. I run some function to return a list of dictionaries that would be assign to initial attribute of the formset.

class OntoRecAPView(FormView):
    form_class = APReviewForm
     .....
    def get_context_data(self, **kwargs):
        context = super(OntoRecAPView, self).get_context_data(**kwargs)
        if self.request.POST:
            context['formset'] = APReviewFormSet()
        else:
            review = returnResults(self.kwargs['webAttack'])
            if not review:
                pass
            else:
                context['formset'] = APReviewFormSet(initial=review)
                return context

If you need more context, please let me know. I got it to work with current setup, but if there any elegant way to make the functionality I am game.