2

I'm following along in the DAL documentation to add a filtered field to my form, but the forwarding isn't working to connect one field to the other:

Forms.py

class PurchaseForm(forms.ModelForm):

    commodity = forms.ModelChoiceField(
        queryset=Commodity.objects.all(),
        widget=autocomplete.ModelSelect2(url='commodity-autocomplete'),
        required=False,
    )

    class Meta:
        model = Purchase
        fields = ["variety"]
        widgets = {
            'variety': autocomplete.ModelSelect2(url='variety-autocomplete', forward=['commodity'],   
        }

Views.py

class VarietyAutocompleteView(autocomplete.Select2QuerySetView):
    def get_queryset(self):
        qs = Variety.objects.all()

        commodity = self.forwarded.get('commodity', None)
        print("Commodity:" + str(commodity))
        if commodity:
            qs = qs.filter(commodity=commodity)

        if self.q:
            qs = qs.filter(name__istartswith=self.q)

        return qs

I'd like my Variety choices to be filtered by their foreign key relationship to Commodity objects. Both autocomplete fields are working on their own just fine, but the choice from the commodity field is not being forwarded to the VarietyAutocompleteView (my print command prints Commodity:None). Is this perhaps because I am passing a foreign key object? Or have I set this up incorrectly somehow?

Adam Starrh
  • 6,428
  • 8
  • 50
  • 89

2 Answers2

2

I had to scrap DAL and move to Bootstrap Combobox. It turned out to be really easy to implement, provided you are using the Bootstrap libraries.

This is how it is set up:

Add class combobox to the select widget:

forms.py

from django import forms

from Business.models import Company, Branch
from .models import Variety

class PurchaseForm(forms.ModelForm):

    variety = forms.ModelChoiceField(
        queryset=Variety.objects.all(),
        widget=forms.Select(attrs={'class': 'combobox'}),
        required=False
    )

    class Meta:
        model = Purchase
        fields = [
            "invoice", "contract_date", ...
        ]

Then, insert the simplest javascript snip ever:

inventory_report.html

....

<td style="padding-bottom: 10px">
    <div>Supplier:</div>
    <div>{{ view.purchase_form.supplier }}</div>
</td>

....
{% block scripts %}
    <script type="text/javascript" src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
    <script type="text/javascript" src="{% static 'js/bootstrap-combobox.js' %}"></script>

        $(document).ready(function(){

            // Set Text Autofields on New Contract
           $('.combobox').combobox();

        });

    </script>
    {{ view.purchase_form.media }}
{% endblock %}

That's all there is to it.

Adam Starrh
  • 6,428
  • 8
  • 50
  • 89
1

I'll add for anyone else like me who is thinking "yeah, but I still really don't want to change" - that in practice the line:

 'variety': autocomplete.ModelSelect2(url='variety-autocomplete', forward=['commodity'])

Really did not work for me either, but changing it to something like:

 'variety': autocomplete.ModelSelect2(url='variety-autocomplete', forward=('commodity', ))

Did work. Notice that it's a tuple so you need to have a "," there to make it work, as it's supposed to be an iterable value.

I didn't dig much further into why an array is part of the docs and yet doesn't work, but that was the critical change that make my variant work.

Also - I was using a formset (so there were prefixes) and that proved to not be a problem.

bethlakshmi
  • 4,581
  • 22
  • 44