【问题标题】:Can't save ManyToMany using MultipleChoiceField无法使用 MultipleChoiceField 保存多对多
【发布时间】:2015-09-11 21:24:13
【问题描述】:

我正在尝试在 MultipleChoiceField 中使用自定义 CHOICE。我可以保存所有内容,但不能保存员工。

models.py

class Employee(models.Model):
    employee_id = models.CharField(max_length=20, unique=True)

    def __str__(self):
        return '%s' % self.employee_id


class Task(models.Model):
    employee = models.ManyToManyField(Employee, blank=True, null=True)
    task = models.CharField(max_length=100)
    comment = models.CharField(max_length=200)

    def __str__(self):
        return '%s' % self.task

forms.py

class TaskCreateForm(forms.ModelForm):

    CHOICES = (
        ('123', 'Adam'),
        ('321', 'John'),
        ('666', 'Lucy'),
    )

    employee = forms.MultipleChoiceField(choices=CHOICES, required=True)


    def __init__(self, custom_choices=None, *args, **kwargs):
        super(TaskCreateForm, self).__init__(*args, **kwargs)
        if custom_choices:
            self.fields['employee'].choices = custom_choices

    class Meta:
        model = Task

所以基本上我添加了custom_choices,因为我想在MultipleChoiceField 中显示员工姓名('Adam', 'John' ,'Lucy') 并保存他们的

employee_id('123','321', 666')。

views.py

class TaskCreateView(CreateView):
    model = Task
    form_class = TaskCreateForm
    template_name = "task/create.html"

    def form_valid(self, form):
        self.object = form.save()
        return redirect('/task_page/')

我可以在我的页面上看到表格,我可以选择员工,但employee_id 没有保存。仅保存其他字段 taskcomment

更新说明:

我的模型中没有名字。我只想显示employee_id自定义 名称。 这就是我需要 ('123','Adam') 的原因 - 我想保存 '123' 但以我的形式显示 'Adam'

【问题讨论】:

    标签: django django-models django-forms django-views


    【解决方案1】:

    嗯,基本的解决方案还是一样的:

    queryset=Employee.objects.filter(employee_id__in=['some_id', 'other_id'])
    

    关键是你应该使用ModelMultipleChoiceField

    如果您想显示名称而不是 ID,有几种方法可以做到这一点,例如模型上的 get_name 方法和自定义 ModelMultipleChoiceField,如下所述:https://stackoverflow.com/a/3167840/1180983

    所以看起来大概是这样的:

    EMPLOYEE_NAMES = {
        '123': 'Adam',
        '321': 'John',
    }
    
    class Employee(models.Model):
        employee_id = models.CharField(max_length=20, unique=True)
    
        def get_name(self):
            return EMPLOYEE_NAMES.get(self.employee_id, 'unknown')
    
    class EmployeeMultipleChoiceField(ModelMultipleChoiceField):
        def label_from_instance(self, obj):
            return obj.get_name()
    
    class TaskCreateForm(forms.ModelForm)
        employees = EmployeeMultipleChoiceField(
            queryset=Employee.objects.filter(employee_id__in=['123', '321'])
        )
    

    【讨论】:

    • 嘿,我在 TaskCreateForm 中突出显示了 AttributeError: 'module' object has no attribute 'EmployeeMultipleChoiceField' PyCharm EmployeeMultipleChoiceField
    • 你应该把forms.EmployeeMultipleChoiceField改成EmployeeMultipleChoiceField
    • 不幸的是,我只能看到 ID。我完全按照你的方式进行了
    • 我做了一个快速测试。这种方法对我有用。您是否可能在表单上使用了我建议的复数名称(employees),但忘记相应地更改模型上的字段名称(employee)?
    • 这是一个带有小演示的 hg 存储库:bitbucket.org/rfleschenberg/so-31047499 请注意:这不是干净的代码,它只是作为一个非常快速和肮脏的演示来帮助您跟踪问题。当涉及到诸如import *之类的事情时,不要效仿我。
    【解决方案2】:

    您的 ModelForm 不知道如何处理 save() 上的员工字段,因为您没有在任何地方告诉它,并且该字段未连接到任何模型。请改用ModelMultipleChoiceField

    如果您需要限制 ModelMultipleChoiceField 允许的选择,请使用 queryset 参数:

    employees = forms.ModelMultipleChoiceField(
        queryset=Employee.objects.filter(name__in=['Alice', 'Bob'])
    )
    

    另外,想想在哪里使用复数和在哪里使用单数名称,这样你就不会混淆自己(employees 而不是上面的employee)。

    【讨论】:

    • 不,不,你们不明白。我只需要显示名称并保存employee_id。在我的模型中没有名字。我只想显示在选择字段名称中,但只保存 ID。
    • Employee 模型只包含employee_id。我没有任何名字。我只想显示employee_id 的自定义名称。我更新了我的帖子
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-21
    • 1970-01-01
    • 1970-01-01
    • 2012-12-05
    • 1970-01-01
    相关资源
    最近更新 更多