如何使用TextInput小部件来获取Django外键来显示名称而不是id?

时间:2012-01-12 22:59:28

标签: django django-forms

我有以下(本例简化)Django模型:

class Ingredient(models.Model):
    name = models.CharField(max_length=100)

    def __unicode__(self):
        return self.name

class RecipeIngredient(models.Model):
    quantity = models.DecimalField(max_digits=5, decimal_places=3)
    unit_of_measure = models.ForeignKey(UnitOfMeasure)
    ingredient = models.ForeignKey(Ingredient)
    comment = models.CharField(max_length = 40, blank=True)

    def __unicode__(self):
        return self.id

我有以下表格:

class RecipeIngredientForm(ModelForm):

    class Meta:
        model = RecipeIngredient

    def __init__(self, *args, **kwargs):
        super(RecipeIngredientForm, self).__init__(*args, **kwargs)
        self.fields['quantity'].widget = forms.TextInput(attrs={'size':'6'})
        self.fields['ingredient'].widget = forms.TextInput(attrs={'size':'30'})
        self.fields['comment'].widget = forms.TextInput(attrs={'size':'38'})

当我查看表单时,成分按其id值显示,而不是其名称。如何显示名称而不是ID?

更新

一个解决方案(更优雅的想法仍然受欢迎)是继承TextInput小部件并使用该值来获取成分名称:

class IngredientInput(forms.TextInput):
    def render(self, name, value, attrs=None):
        new=Ingredient.objects.get(pk=value).name
        value=new
        if value is None:
            value = ''
        final_attrs = self.build_attrs(attrs, type=self.input_type, name=name)
        if value != '':
            # Only add the 'value' attribute if a value is non-empty.
            final_attrs['value'] = force_unicode(self._format_value(value))
        return mark_safe(u'<input%s />' % flatatt(final_attrs))

3 个答案:

答案 0 :(得分:4)

我通过覆盖表单上__init__内的字段查询集来解决了这个用例。仍然会显示选择输入,但它只有一个选项。由于选择的选项太多,我和OP有同样的问题。

class PaymentForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(PaymentForm, self).__init__(*args, **kwargs)
        instance = kwargs.get("instance", None)

        if instance and instance.id and instance.reconciled_by:
            self.fields["reconciled_by"].queryset = User.objects.filter(
                id=instance.reconciled_by.id
            )

答案 1 :(得分:0)

我有一个类似的问题并且像这样(Python 3)非常类似地解决了这也使用超类来进行渲染而不是再次重写它。 我添加了一个我想要的功能,即将字段设为只读,我把它留下来,因为我认为它可能对编辑你想要的东西很有用:

class IngredientInput(forms.TextInput):

   def render(self, name, value, attrs=None):
        new=Ingredient.objects.get(pk=value).name
        value = self._format_value(new)
        attrs['readonly'] = True
        return super(IngredientInput, self).render(name, value, attrs)

答案 2 :(得分:-1)

IT会显示ID,因为您这样说:

class RecipeIngredient(models.Model):
    def __unicode__(self):
        return self.id

编辑:

...还有,因为你使用的是TextInput

self.fields['ingredient'].widget = forms.TextInput(attrs={'size':'30'})

我想你需要这个: https://docs.djangoproject.com/en/1.3/ref/forms/fields/#modelchoicefield