我有一个叫做projects的应用程序。其中一个字段是contributors
,其中用户列表与ManyToManyField
一起存储。我试图使它有可能添加和删除用户到和从列表。添加已经相当容易使用ModelChoiceField
与所有用户的传递查询集。从列表中删除一个用户仍然困扰着我。我想了解的是如何以及在哪里传递额外的参数,以便我可以处理表单中的查询,因此它只会列出来自特定项目的用户。
models.py
# Model for projects
class Project(models.Model):
...
contributors = models.ManyToManyField(User, blank=True)
...
forms.py
class AddUserForm(forms.Form):
user = forms.ModelChoiceField(queryset=User.objects.all())
class Meta:
model = Project
fields = [
"user",
]
views.py
# Add task to a project
@login_required()
def projects_adduser(request, id):
# Fetch the project if it exists
project = get_object_or_404(Project, id=id)
# Form for adding users to contributors list
form = AddUserForm(request.POST or None)
# Validate the form
if form.is_valid():
user = form.cleaned_data.get("user")
project.contributors.add(user)
project.save()
messages.success(request, "User successfully added to project!")
return HttpResponseRedirect(project.get_edit_url())
# Context dict to return for template
context = {
"title": "Add user to project: " + project.title,
"form": form,
"instance": project,
}
return render(request, template + '/form.html', context)
您可以像这样将初始用户的queryset传递给表单:
form = AddUserForm()
form.fields["user"].queryset = User.objects.filter(project=project)
另外,您不需要调用project.save()
, project.contributors.add(user)
已经执行查询来添加m2m连接
我决定从这个周末开始帮助那些在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):
。所以我给了pk=1在url测试像这个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的旅程好运!和平!