Change Django ModelChoiceField to show users' full names rather than usernames

后端 未结 5 1081
不知归路
不知归路 2020-11-30 01:31

I have a form in my Django app (not in admin) that allows staff members to select a user from a dropdown.

forms.ModelChoiceField(queryset = User.objects.filt         


        
相关标签:
5条回答
  • 2020-11-30 01:34

    When working with a ModelForm, I found the following most useful so that I didn't have to redefine my queryset - in particular because I used limit_choices_to in the model definition:

    class MyModelForm(forms.ModelForm):
        def __init__(self, *args, **kwargs):
            super(MyModelForm, self).__init__(*args, **kwargs)
            self.fields['user'].label_from_instance = lambda obj: "%s" % obj.get_full_name()
    

    customised from this answer https://stackoverflow.com/a/7805824/432992

    0 讨论(0)
  • 2020-11-30 01:42

    You can override the field with a custom ModelChoiceField and change the label_from_instance function to return get_full_name instead. See the docs for ModelChoiceField: http://docs.djangoproject.com/en/1.2/ref/forms/fields/#modelchoicefield

    0 讨论(0)
  • 2020-11-30 01:53

    If you want to change choices of the field in model form, try this adaptation of the Bartek's answer:

    model:

    class MyModel(models.Model)
        user = models.ForeignKey(...)
    

    form field:

    class UserModelChoiceField(forms.ModelChoiceField):
        def label_from_instance(self, obj):
            return obj.get_full_name()
    

    form:

    class MyModelForm(forms.ModelForm):
        class Meta:
            model = MyModel
            fields = ['user']
            field_classes = {
                'user': UserModelChoiceField
            }
    

    This approach will preserve params of the field (you don't need to specify queryset, required and so on).

    0 讨论(0)
  • 2020-11-30 01:54

    You can setup a custom ModelChoiceField that will return whatever label you'd like.

    Place something like this within a fields.py or wherever applicable.

    class UserModelChoiceField(ModelChoiceField):
        def label_from_instance(self, obj):
             return obj.get_full_name()
    

    Then when creating your form, simply use that field

     UserModelChoiceField(queryset=User.objects.filter(is_staff=False), required = False)
    

    More info can be found here

    0 讨论(0)
  • 2020-11-30 01:56

    You can also make one custom ModelChoiceField to which you can pass a function. That way if you have different fields for which you want different attributes to be displayed, you can have only 1 class:

    class CustomModelChoiceField(forms.ModelChoiceField):
    name_function = staticmethod(lambda obj: obj)
    
    def __init__(self, name_function, *args, **kwargs):
        if not name_function is None: self.name_function = name_function
        super(CustomModelChoiceField, self).__init__(*args, **kwargs)
    
    def label_from_instance(self, obj):
         return self.name_function(obj);
    

    You can then call it as simply as this:

    form_field = CustomModelChoiceField(
        lambda obj: obj.get_full_name(),
        queryset=Whatever.objects.all(),
    )
    

    You can also pass None in case you're doing some dynamic stuff and it'll just basically default to a regular ModelChoiceField. I'm not too much of a python guy but this works for me.

    0 讨论(0)
提交回复
热议问题