applegrew / django-select2

This is a Django integration for Select2
MIT License
719 stars 314 forks source link

Fields vs widgets #84

Closed dyve closed 10 years ago

dyve commented 10 years ago

I notice that especially on ModelForms a lot of info is lost if you manually add a field. Labels are no longer taken from model definition (verbose_name) for example.

It would be great if we could just define widgets instead of fields. Looking at the demo app, I see that a lot of the definition (query set, lookups) is now in the field definition.

Is it possible to just configure a widget, and leave the field out of the definition. A form would then look like

class EmployeeForm(...):

    class Meta:
        fields = ('manager', )
        widgets = { 'manager': ManagerSelect2HeavySelect() }

Thanks for any info

applegrew commented 10 years ago

I am not sure if I understand your question. Widgets are supposed to be concerned with handling the rendering of the UI (html code in this case). Fields are supposed to store the values and interact with the model. Widgets get all required model info from its underlying field.

All Light fields are drop-in replacement for their Djnago counterpart. So, the widgets used for them should ideally work with Django fields too. However, Heavy fields do not have a corresponding Django counterpart. For example a heavy model backed field needs to assume that the model has too much data, so unlike Django model fields it cannot simply get all records and render them to html.

dyve commented 10 years ago

I will try to explain with examples. What I mean is, if you want to use a django-select2 field in a ModelForm, you are now forced to redfine it.

Example from testapp, I added verbose_name to manager:

class Employee(models.Model):
    name = models.CharField(max_length=30)
    salary = models.FloatField()
    dept = models.ForeignKey(Dept)
    manager = models.ForeignKey('Employee', null=True, blank=True, verbose_name=ugettext_lazy('boss'))

    def __unicode__(self):
        return unicode(self.name)

class EmployeeChoices(AutoModelSelect2Field):
    queryset = Employee.objects
    search_fields = ['name__icontains', ]

class EmployeeForm(forms.ModelForm):
    manager = EmployeeChoices(required=False) # This is a redefinition, the label 'boss' will be lost
    dept = ModelSelect2Field(queryset=Dept.objects) # Again a redefinition

    class Meta:
        model = Employee

In order to use the EmployeeChoices, you have to manually add the field to EmployeeForm. This is normally not necessay, the field is generated by ModelForm, as specified in fields and widgets in Meta class.

What I would like to do is create the form without rewriting the field

class EmployeeForm(forms.ModelForm):

    class Meta:
        model = Employee
        # Now how do I make my form work with select2
        # without redefining fields and losing the information from my model?
dyve commented 10 years ago

The relevant Django documentation is here:

https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#overriding-the-default-fields

applegrew commented 10 years ago

You cannot use heavy widgets, but have you tried using equivalent light widgets?

dyve commented 10 years ago

No, because for this project I need the Heavy Widgets :-(

applegrew commented 10 years ago

Sorry heavy widgets need this arrangement. Unlike typical Django widgets, this needs to get new values via ajax, so the widget needs to have special arrangement with the field to get this value.

Well, it could have been a better design that widgets did not assume that ajax datasource would always be the field. In that case you could have used heavy fields for your case. However, right now that is not the case.

dyve commented 10 years ago

Ok, thank you for info. I will try to build something that works on widgets alone.

Op 14 dec. 2013, om 07:26 heeft AppleGrew notifications@github.com het volgende geschreven:

Closed #84.

— Reply to this email directly or view it on GitHub.

dyve commented 10 years ago

While investigating this, I noticed that a widget can always retrieve the choices of the field (either query set or normal array) through self.choices.

So the only thing to be moved from Select2 field definition to select2 widget definition would be the filter fields. That does not seem like a big problem. I'm trying to write a solution that just depends on widgets right now, will share code if I succeed.

applegrew commented 10 years ago

Ok