Django - ModelForm Dynamic field update

后端 未结 4 823
情书的邮戳
情书的邮戳 2021-01-06 11:50

I\'m trying to update certain fields a ModelForm, these fields are not fixed. (I have only tutor that is autopopulated by the view)

Model:



        
相关标签:
4条回答
  • 2021-01-06 12:38

    Put your form fields as nullable and with "clean" methods you can add logic to fields ex:

    class SessionForm(forms.ModelForm):
        def clean_end_date(self):
            cd = self.cleaned_data
            if (cd["start_date"] and cd["end_date"]) and cd["end_date"] < cd["start_date"]:
                raise forms.ValidationError("WTF?!")
            if not (cd["start_date"] or cd["end_date"]):
                raise forms.ValidationError("need one date")
            return cd['end_date']
    

    If you want to change value, use a different value to the return statement.

    This is what you may need for validation.

    If you want, you may copy GET dictionary in your view and update values before instanciate your form

    def my_view(request):
        r_data = request.GET.copy()
        r_data.merge(request.POST)
    
        data = dict([(key, my_function(key, value)) for key, value in r_data.iteritems() if key in MyForm.fields])
        form = MyForm(data=data)
        [...]
    

    hopes it help.

    0 讨论(0)
  • 2021-01-06 12:44

    Your question suggests that you have a requirement that uses same model but different fields are hidden in your ModelForm, based on your needs.

    If I understand your question, then you need to Create two different ModelForm based class, both these classes have same model value inside the Meta class. Exclude and include the fields you need. So now you have different ModelForm classes which you can call inside your view logic.

    With this you will have two different forms that depend on same model, with different default fields.

    With clever url and view design you will be able to use the above idea to serve multiple forms from same model.

    0 讨论(0)
  • 2021-01-06 12:45

    You can invoke form's constructor like this:

    class SessionForm(forms.ModelForm):
        class Meta:
            model = Session
            exclude = ['tutor', 'start_time']
    
        def __init__(self, your_extra_args, *args, **kwargs):
            super(SessionForm, self).__init__(*args, **kwargs)
            if need_end_time_start_time(your_extra_args):
                self.fields['start_time'] = forms.DateTimeField()     
    

    To use this class, you have to pass an argument "your_extra_args" to your form:

    session_form = SessionForm('foo')
    
    0 讨论(0)
  • 2021-01-06 12:46

    I've had to do something similar before, and while it isn't exactly pretty, it is quite effective. It involves dynamically creating a type at runtime, and using that type. For some documentation, you can see DynamicModels for django.

    Here we go.. your requirements.

    • You want to be able to update a model using a form
    • You want to selectively specify which fields are to be updated at run-time

    So, some code:

    def create_form(model, field_names):
        # the inner class is the only useful bit of your ModelForm
        class Meta:
            pass
        setattr(Meta, 'model', model)
        setattr(Meta, 'include', field_names)
        attrs = {'Meta': Meta}
    
        name = 'DynamicForm'
        baseclasses = (forms.ModelForm,)
        form = type('DynamicForm', baseclasses, attrs)
        return form
    
    def my_awesome_view(request):
        fields = ['start_time', 'end_time']
        form = create_form(Session, fields)
        # work with your form!
    
    0 讨论(0)
提交回复
热议问题