简体   繁体   中英

Access a form method from generic.UpdateView in Django

I have a view which is a generic.UpdateView , and I need to access a form method - get_hidden_fields() . How do I access it?

I currently used self.form_class().get_hidden_fields() but I'm not sure if this is correct. I think it creates a new instance of the form and I want to use the current instance.

def get_context_data(self, **kwargs):
    cd = super().get_context_data(**kwargs)
    cd.update({
        'matches_list': self.page.object_list,
        'form_hidden_fields': list(self.form_class().get_hidden_fields()),
    })
    return cd

https://github.com/speedy-net/speedy-net/blob/staging/speedy/match/matches/views.py#L54

I can access the form method directly from the template:

{% if field.name in form.get_hidden_fields %}

link

However, if I need to access the form from Python, I think the correct way is to use cd['form'] in get_context_data (after calling cd = super().get_context_data(**kwargs) ).

def get_context_data(self, **kwargs):
    cd = super().get_context_data(**kwargs)
    cd.update({
        'matches_list': self.page.object_list,
        'form_hidden_fields': list(cd['form'].get_hidden_fields()),
    })
    return cd

Update-1: 10th Aug

def get_context_data(self, **kwargs):
    if "form" in kwargs:
        form = kwargs['form']
    else:
        form = self.get_form()
        kwargs['form'] = form

    cd = super().get_context_data(**kwargs)
    self.form_class()
    cd.update({
        'matches_list': self.page.object_list,
        'form_hidden_fields': list(form.get_hidden_fields()),
    })
    return cd

This is another approach that you can use, because when you call get_context_data it will create the form it is not there. This means either you create or let it create the form. If the get_context_data of the inherited class does it, then it does in kwargs which you can't extract without a hacky way.

Original approach

So you can use the approach you have where you initiate the class, or you can use a combo approach where the same method can work as a class method as well as a instance method. The technique is shown in below article

Creating a method that is simultaneously an instance and class method

A demo of the same is below

import functools


class combomethod(object):
    def __init__(self, method):
        self.method = method

    def __get__(self, obj=None, objtype=None):
        @functools.wraps(self.method)
        def _wrapper(*args, **kwargs):
            if obj is not None:
                return self.method(obj, *args, **kwargs)
            else:
                return self.method(objtype, *args, **kwargs)

        return _wrapper


class SpeedyMatchSettingsMiniForm(object):
    @combomethod
    def get_fields(self):
        return ('gender_to_match', 'match_description', 'min_age_to_match', 'max_age_to_match', 'diet_match', 'smoking_status_match', 'relationship_status_match')

    @combomethod
    def get_visible_fields(self):
        return ('diet_match', 'min_age_to_match', 'max_age_to_match')

    @combomethod
    def get_hidden_fields(self):
        fields = self.get_fields()
        visible_fields = self.get_visible_fields()
        return (field_name for field_name in fields if (not (field_name in visible_fields)))


print(list(SpeedyMatchSettingsMiniForm().get_hidden_fields()))
print(list(SpeedyMatchSettingsMiniForm.get_hidden_fields()))

And the output is

['gender_to_match', 'match_description', 'smoking_status_match', 'relationship_status_match']
['gender_to_match', 'match_description', 'smoking_status_match', 'relationship_status_match']

So this way in your case you use the Class object directly

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM