1

I have this URL

path('private/productores/<pk>', views.Productor_Private.as_view()),

Views.py

class Productor_Private(generic.DetailView):
    model = Productor
    template_name = 'firstpage/productor_private.html'

    def get(self, request, pk):
        form = RepartoForm()
        return render(request, self.template_name, {'form': form})

    def post(self, request, pk):
        form = RepartoForm(request.POST)

        if form.is_valid():
            return render(request, self.template_name, args)

I want to retrieve the pk from the URL to use it as a filter inside the forms.py, to do something like this:

class RepartoForm(forms.Form):
    productos = forms.ModelMultipleChoiceField(queryset=Producto.objects.filter(productor=pk))

So in other words, I need to check what the current user's "productor" id is in order to only retrieve the "productos" that belong to this "productor"

1 Answer 1

1

You will need to "patch" the form constructor, and manually set the queryset in the __init__ function:

class RepartoForm(forms.Form):
    productos = forms.ModelMultipleChoiceField(queryset=Producto.objects.all())

    def __init__(self, *args, productor_pk=None, **kwargs):
        super(forms.Form, self).__init__(*args, **kwargs)
        if productor_pk is not None:
            self.fields['productos'].queryset = Producto.objects.filter(
                productor=productor_pk
            )

Or for older versions of Python that does not implement more advanced parameter unpacking, one can implement it like:

class RepartoForm(forms.Form):
    productos = forms.ModelMultipleChoiceField(queryset=Producto.objects.all())

    def __init__(self, *args, **kwargs):
        productor_pk = kwargs.pop('productor_pk', None)
        super(forms.Form, self).__init__(*args, **kwargs)
        if productor_pk is not None:
            self.fields['productos'].queryset = Producto.objects.filter(
                productor=productor_pk
            )

In case no product_pk is given, the queryset are all the Productos (in case you do not want that, you can alter the form, and for example by default use an empty QuerySet like Producto.objects.none()).

Then in the view, you can construct the form with a named productor_pk parameter:

class Productor_Private(generic.DetailView):
    model = Productor
    template_name = 'firstpage/productor_private.html'

    def get(self, request, pk):
        form = RepartoForm(productor_pk=pk)
        return render(request, self.template_name, {'form': form})

    def post(self, request, pk):
        form = RepartoForm(request.POST, productor_pk=pk)

        if form.is_valid():
            return render(request, self.template_name, args)

Note: you also need to cover the case where the form is invalid: right now post will return None for that, but you should return a HTTP response for all codepaths.

Sign up to request clarification or add additional context in comments.

8 Comments

@user6148356: is this by any chance Python-2.x?
@user6148356: updated with a working version for Python-2.x. Note that on January 1, 2020, the support of Python-2.x ends.
Nope, version 3.6.4
@user6148356: sorry made a typo, should now be fixed.
Sorry, I fixed it. in views.py in get you need to pass productor_pk to RepartoForm. So like form=RepartoForm(productor_pk)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.