具有反转manytomy字段的ModelForm

2024-10-01 09:25:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我在让modelmultipechoicefield显示模型实例的初始值时遇到了困难。我还没有找到关于这个领域的任何文档,而且我读过的例子太令人费解了。Django: ModelMultipleChoiceField doesn't select initial choices看起来很相似,但是给出的解决方案对模型实例不是动态的。在

以下是我的案例(每个数据库用户都连接到一个或多个项目):

在模型.py在

from django.contrib.auth.models import User
class Project(Model):
    users = ManyToManyField(User, related_name='projects', blank=True)

在表单.py在

^{pr2}$

在视图.py在

def assign(request):
    if request.method == 'POST':
        form = AssignProjectForm(request.POST, instance=request.user)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect('/index/')
    else:
        form = AssignProjectForm(instance=request.user)

    return render_to_response('assign.html', {'form': form})

它返回的表单没有选择实例的链接项目(看起来像:Django multi-select widget?)。此外,它不会用保存表单时所做的任何选择来更新用户。在

编辑:使用以下方法成功地解决了这个问题:http://code-blasphemies.blogspot.com/2009/04/dynamically-created-modelmultiplechoice.html


Tags: 项目django实例用户py模型form表单
2条回答

这里有一个比旧的更好的解决方案,它确实不起作用。在

在创建表单时,您必须从数据库加载现有的相关值,并在保存表单时将它们保存回。我对相关名称(manager)使用set()方法,它为您完成所有工作:删除不再被选中的现有关系,并添加已被选中的新关系。所以你不必做任何循环或检查。在

class AssignProjectForm(ModelForm):

    def __init__(self, *args, **kwargs):
        super(AssignProjectForm, self).__init__(*args, **kwargs)

        # Here we fetch your currently related projects into the field,     
        # so that they will display in the form.
        self.fields['projects'].initial = self.instance.projects.all(
            ).values_list('id', flat=True)

    def save(self, *args, **kwargs):
        instance = super(AssignProjectForm, self).save(*args, **kwargs)

        # Here we save the modified project selection back into the database
        instance.projects.set(self.cleaned_data['projects'])

        return instance

除了简单之外,使用set()方法还有另一个好处,如果您在m2m关系中使用Django信号(例如post_save等):如果您在循环中一次添加和删除一个条目,您将获得每个对象的信号。但是如果您在一个操作中使用set()来完成它,那么您将只得到一个带有对象列表的信号。如果信号处理程序中的代码执行了重要的工作,则这是一个大问题。在

ModelForm不会自动用于反向关系。在

save()上没有发生任何事情,因为ModelForm只知道如何处理它自己的字段projects不是{}模型上的字段,它只是表单上的一个字段。在

你必须告诉你的窗体如何用你的新字段来保存自己。在

def save(self, *args, **kwargs):
    for project in self.cleaned_data.get('projects'):
        project.users.add(self.instance)
    return super(AssignProjectForm, self).save(*args, **kwargs)

相关问题 更多 >