使用Django中ManyToManyField的特定参数自定义表单中的查询

时间:2016-10-22 05:07:32

标签: python django forms django-queryset manytomanyfield

我有一个叫做项目的应用。其中一个字段是modelBuilder.Entity<Equipment>().Property(p => p.Settings).HasColumnType("json"); ,其中用户列表与contributors一起存储。我试图在列表中添加和删除用户。使用ManyToManyField通过所有用户的传递查询集添加相当容易。从列表中删除用户仍然无法实现。我试图理解的是如何以及在何处传递其他参数以便我可以在表单中处理查询,因此它只列出来自特定项目的用户。

添加用户

models.py

ModelChoiceField

forms.py

# Model for projects
class Project(models.Model):
    ...
    contributors = models.ManyToManyField(User, blank=True)
    ...

views.py

class AddUserForm(forms.Form):
    user = forms.ModelChoiceField(queryset=User.objects.all())

    class Meta:
        model = Project
        fields = [
            "user",
        ]

2 个答案:

答案 0 :(得分:3)

您可以将初始用户queryset传递给如下形式:

form = AddUserForm()
form.fields["user"].queryset = User.objects.filter(project=project)

此外,您无需致电project.save()project.contributors.add(user)已执行查询以添加m2m连接

答案 1 :(得分:2)

我决定在本周末帮助那些在stackoverflow中使用Django的人。我通常在这里发帖提问。我认为是时候给人们回答了。这是我的开始!精彩!我使用Django WebFramework的时间不到2个月。所以我的回答可能还不够,或者还有其他更好的方法。但我这样想出来解决你的问题。 (甚至我亲自用我的笔记本电脑测试自己的代码!)

我的示例代码在这里

models.py

from django.db import models
from django.contrib.auth.models import User

# Create your models here.
class Project(models.Model):
    contributors = models.ManyToManyField(User, blank=True)

views.py

from django.shortcuts import render, get_object_or_404
from django.http import HttpResponseRedirect
from barrierfree.models import Project
from barrierfree.forms import AddUserForm

# Create your views here.
def projects_adduser(request, id):

    # Fetch the project if it exists
    project = get_object_or_404(Project, pk=id)
    pk_number_project = project.pk
    # Form for adding users to contributors list
    form = AddUserForm(request.POST, project=pk_number_project)

    # Validate the form
    if form.is_valid():
        user = form.cleaned_data.get("user")
        print ("validated!")
        return HttpResponseRedirect('/Sucess')    
    # Context dict to return for template

    return render(request, 'test.html', {'form':form})

urls.py

from django.conf.urls import url
from . import views
urlpatterns = [
    url(r'^test/$', views.projects_adduser, {'id':1}, name='test'),
]

的test.html

<form action="." method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="OK">
</form>

forms.py

from django import forms
from django.contrib.auth.models import User
from barrierfree.models import Project

class AddUserForm(forms.Form):
    user = forms.ModelChoiceField(queryset=None)

    class Meta:
        model = Project
        fields = [
            "user",
        ]

    def __init__(self, *args, **kwargs):
        pk_num_project = kwargs.pop('project', None)
        print (pk_num_project)
        super(AddUserForm, self).__init__(*args, **kwargs)
        self.fields['user'].queryset = User.objects.all().filter(project__pk=pk_num_project)

这里是解释如何做到这一点。

当我阅读您的代码时,您似乎通过视图参数传递了特定项目的pk编号。因为你写了def projects_adduser(request, id):。所以我在url中给pk = 1进行测试,就像这个url(r'^test/$', views.projects_adduser, {'id':1}, name='test')一样,然后你将在启动表单实例时传递与pk编号匹配的项目实例。 form = AddUserForm(request.POST, project=pk_number_project)然后您将只显示此项目中的用户。

def __init__(self, *args, **kwargs):
        pk_num_project = kwargs.pop('project', None)
        print (pk_num_project)
        super(AddUserForm, self).__init__(*args, **kwargs)
        self.fields['user'].queryset = User.objects.all().filter(project__pk=pk_num_project)

然后通过覆盖 init 方法初始化要在表单中显示的数据。

queryset = User.objects.all().filter(project__pk=pk_num_project)

你可以这样过滤,因为User和Project是N:N关系。

我希望我能正确理解你的问题并给你正确答案:)祝我们在Django之旅中好运!和平!