使用 Django 中的 ManyToManyField 的特定参数在表单中自定义查询
Customize query in forms with specific arguments for ManyToManyField in Django
我有一个名为 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)
我决定从这个周末开始帮助在 Whosebug 中使用 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 的旅途中好运!和平!
您可以将初始用户查询集传递给这样的表单:
form = AddUserForm()
form.fields["user"].queryset = User.objects.filter(project=project)
此外,您不需要调用 project.save()
,project.contributors.add(user)
已经在执行查询以添加 m2m 连接
我有一个名为 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)
我决定从这个周末开始帮助在 Whosebug 中使用 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 的旅途中好运!和平!
您可以将初始用户查询集传递给这样的表单:
form = AddUserForm()
form.fields["user"].queryset = User.objects.filter(project=project)
此外,您不需要调用 project.save()
,project.contributors.add(user)
已经在执行查询以添加 m2m 连接