Django编辑模型模板 - 如何仅选择要在(外键)模型下拉列表的编辑模板中显示的文本值?

时间:2017-03-23 08:12:32

标签: django django-models django-forms django-templates

我正在为我的模型创建一个编辑视图,该视图具有对另一个表的引用。 我正在使用的模型如下所示:

class SkillSet(models.Model):
SKILL_LEVEL_CHOICES = (
    (0, 'None'),
    (1, 'Basic'),
    (2, 'User'),
    (3, 'Advanced'),
    )

rating = models.ForeignKey(Rating, on_delete=models.CASCADE)
skill = models.ForeignKey(Skill)
skillLevel = models.IntegerField(choices = SKILL_LEVEL_CHOICES, default = 0)
notes = models.TextField(null=True, blank=True)

我为此创建了一个表单,您可以在此处看到:

class SkillSetEditForm(forms.ModelForm):
class Meta:
    model = SkillSet
    fields = [
        "skill",
        "skillLevel",
        "notes"
        ]
    labels = {
        'skill': ('Skill'),
        'skillLevel': ('Skill Level'),
        'notes': ('Notes'),
    }

然后我把它放在我的视图中:

{% for skillForm in skillForms %}
   <tr class="nivEdit" style="display:none;">
       <td>{{ skillForm.skill }}</td>
       <td>{{ skillForm.skillLevel }}</td>
       <td>{{ skillForm.notes}}</td>
   </tr>
{% endfor %}    

最终结果看起来不错,但我不希望我的用户能够编辑技能本身,只需要编辑级别和注释。我可以获得值,但这只是技能模型的基础ID。有没有办法让我从下拉列表中选择显示的文字?我可以用jquery / javascript做到这一点,但它会变得非常混乱,我希望在django中已经有了解决方案。

2 个答案:

答案 0 :(得分:0)

如果您不希望用户设置级别,只需将其从SkillSetEditForm.fields中删除即可。您必须自己在视图中添加它或在模型中设置为null = True, blank = True

如果您想显示技能名称而不是ID,则应将__unicode__方法添加到Skill模型中(但由于您从表单中删除它,因此无关紧要)。< / p>

如果您仍需要表单中的此字段,则可以使用Django 1.9+字段选项disabledhttps://docs.djangoproject.com/en/1.9/ref/forms/fields/#disabled

您可以在SkillSetEditForm课程中尝试类似的内容:

def __init__(self, *args, **kwargs):
  super(SkillSetEditForm, self).__init__(*args, **kwargs)
  self.fields['skill'].disabled = True

答案 1 :(得分:0)

我试图将模型中的某些字段转换为只读字段时遇到了类似的问题。据我所知,没有内置的方式来处理这个优雅。您可以从表单中完全省略skill字段,并通过在模板中呈现模型实例的相应字段来显示相关信息。作为一个替代品,我将以下mixin用于我的表单类:

class ReadonlyMixin(object):

    def __init__(self, **kwargs):
        super(ReadonlyMixin, self).__init__(**kwargs)
        self.readonly_fields = self.get_readonly_fields()
        self.disable_readonly_fields()

    def get_readonly_fields(self):
        return []

    def disable_readonly_fields(self):
        for field_name in self.readonly_fields:
                field = self.fields[field_name]
                field.required = False
                field.widget.attrs.update({'readonly': True})
                if isinstance(field, forms.ModelChoiceField):
                    selected = getattr(self.instance, field_name, None)
                    pk = selected.pk if selected else None
                    field.queryset = field.queryset.filter(pk=pk)

    def clean(self):
        self.clean_readonly_fields()

    def clean_readonly_fields(self):
        for field_name in self.readonly_fields:
            if field_name in self.fields.keys():
                self.cleaned_data[field_name] = getattr(self.instance, field_name)

这会将readonly属性附加到get_readonly_fields返回的字段,以便无法在浏览器中编辑相应的输入。它还限制所选输入的选择输入中的选择。为了防止用户通过操作html代码并将其发送回服务器来编辑只读字段,clean_readonly_fields将使用模型实例的相应数据替换从客户端接收的数据。

像这样使用mixin:

class SkillSetEditForm(ReadonlyMixin, forms.ModelForm):
    ...
    def get_readonly_fields(self):
        return ['skill']