简体   繁体   中英

UpdateView not populating form with existing data

So I have my UpdateView set up to send a request object to the form so I can modify a queryset in the form (based on request.user )

my views.py:

class DataSourceUpdateView(UpdateView):
    model = DataSource
    form_class = DataSourceForm
    template_name = 'engine/datasource_update.html'

    def get(self, request, *args, **kwargs):

        obj = DataSource.objects.get(pk=kwargs['pk'])
        self.object = None
        form = DataSourceForm(request)
        return self.render_to_response(
            self.get_context_data(form=form,
                                  object=obj))

    def post(self, request, *args, **kwargs):

        form = DataSourceForm(request, request.POST, request.FILES)

        if form.is_valid:
            return self.form_valid(form)
        else:
            return self.form_invalid(form)  

my forms.py:

class DataSourceForm(forms.ModelForm):

    def __init__(self, request, *args, **kwargs):
        self.request = request
        super(DataSourceForm, self).__init__(*args, **kwargs)  
        self.fields['dataset_request'].queryset = DatasetRequest.objects.filter(
            creator=self.request.user)

    class Meta:
        model = DataSource
        exclude = ('creator', 'vote_score', 'num_vote_up',
                   'num_vote_down', 'file_size', 'slug')

My problem is, in the template, the form is not populated with existing values. How can I fix this?

With UpdateView it's a little bit tricky. So, in order to initialize your form's data, you need to do it in the view itself not in the form.

So here is how you can perform what's you've done when using UpdateView :

class DataSourceUpdateView(UpdateView):
    model = DataSource
    form_class = DataSourceForm
    template_name = 'engine/datasource_update.html'
    # An empty dict or add an initial data to your form
    initial = {}
    # And don't forget your success URL
    # or use reverse_lazy by URL's name
    # Or better, override get_success_url() method
    # And return your success URL using reverse_lazy
    sucess_url = '/' 

    def get_initial(self):
        """initialize your's form values here"""

        base_initial = super().get_initial()
        # So here you're initiazing you're form's data
        base_initial['dataset_request'] = DatasetRequest.objects.filter(
            creator=self.request.user
        )
        return base_initial

        #... The rest of your view logic

And you're form will be:

class DataSourceForm(forms.ModelForm):

    class Meta:
        model = DataSource
        exclude = (
            'creator',
            'vote_score',
            'num_vote_up',
            'num_vote_down',
            'file_size',
            'slug'
        )

Bonus:

In order to understand why you need to initialize the form's data, you need to see the `UpdateView's MRO which are Visit this documentation link :

  • ...
  • django.views.generic.edit.FormMixin # => This one is dealing with the form
  • ...

And the FormMixin have these attributes and methods visit the documentation link which are:

  • initial : A dictionary containing initial data for the form. ...
  • get_initial() : Retrieve initial data for the form. By default, returns a copy of initial.

Also i recommend you to see what the FormMixin have like attributes and methods in order to see how you can override them or let Django do magics for you :D. See this documentation link

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