ModelSelect2Widget 的属性错误
AttributeError with ModelSelect2Widget
我安装了 Django-Select2 并将其应用到我的项目中,但我遇到了一个无法解决的错误。
这是我的 forms.py
文件:
from django.forms import modelform_factory
from django_select2 import forms as s2forms
from .models import Employer, JobListing, Category_JobListing
class LocationWidget(s2forms.ModelSelect2Widget):
search_fields = [
"location__icontains",
]
def get_queryset(self):
return Employer._meta.get_field("location").choices
EmployerForm = modelform_factory(Employer, fields=["name", "location", "short_bio", "website", "profile_picture"], widgets={"location": LocationWidget})
views.py
文件(仅相关代码部分):
def submitJobListing(request):
if request.method == "POST":
employer_form = EmployerForm(request.POST, request.FILES)
employer = employer_form.save()
return HttpResponse("Your form has been successfully submitted.")
else:
employer_form = EmployerForm()
context = {
"employer_form": employer_form,
}
return render(request, 'employers/submit_job_listing.html', context)
submit_job_listing.html
(我的模板文件):
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ employer_form }}
<input type="submit" value= "Submit">
</form>
使用这段代码,我得到:
AttributeError at /submit-job-listing/
'list' object has no attribute 'none'
输出表明错误与模板中的 {{ employer_form }}
和视图中的 return render(request, 'employers/submit_job_listing.html', context)
有关。
我知道发生这个错误是因为我重写了LocationWidget
中的get_queryset()
方法,但我不知道我做错了什么。
这里有什么问题,我该如何解决?
更新 1:
我遇到一个问题 NoReverseMatch at /submit-job-listing/ Reverse for 'location_choices' not found. 'location_choices' is not a valid view function or pattern name.
。这很可能是我的整个项目中答案代码集成的问题。我不明白为什么会这样。当我收到错误消息时,我尝试访问的 URL 是 http://127.0.0.1:8000/submit-job-listing/
.
相关代码如下:
forms.py
:
from django.forms import modelform_factory
from django_select2 import forms as s2forms
from .models import Employer, JobListing, Category
from django import forms
class LocationWidget(s2forms.HeavySelect2Widget):
data_view = "location_choices"
def __init__(self, attrs=None, choices=(), **kwargs):
super().__init__(attrs=attrs, choices=choices, data_view=self.data_view, **kwargs)
EmployerForm = modelform_factory(Employer, fields=["name", "location", "short_bio", "website", "profile_picture"], widgets={"location": LocationWidget})
JobListingForm = modelform_factory(JobListing, fields=["job_title", "job_description", "job_requirements", "what_we_offer", "job_application_url", "categories"])
urls.py
:
from django.urls import path
from . import views
app_name = "employers"
urlpatterns = [
path("", views.ListJobListingsView.as_view(), name="list_joblistings"),
path("choices/location.json", views.LocationChoicesView.as_view(), name="location_choices"),
path("<int:pk>/", views.DetailJobListingView.as_view(), name="detail_joblisting"),
# path("employers/", views.IndexEmployersView.as_view(), name="index"),
path("employers/<int:pk>/", views.DetailEmployerView.as_view(), name="detail_employer"),
path("submit-job-listing/", views.submitJobListing, name="submit_job_listing"),
# path("submit-job-listing/success/", )
]
views.py
:
def submitJobListing(request):
if request.method == "POST":
employer_form = EmployerForm(request.POST, request.FILES)
job_listing_form = JobListingForm(request.POST, request.FILES)
#check if employer with that name already exists
employer_name = str(request.POST.get("name", ""))
employer_with_the_same_name = Employer.objects.get(name=employer_name)
employer = None
if (employer_with_the_same_name != None):
employer = employer_with_the_same_name
if employer == None and employer_form.is_valid() and job_listing_form.is_valid():
employer = employer_form.save()
job_listing = job_listing_form.save(commit=False)
job_listing.employer = employer
job_listing.save()
#return HttpResponseRedirect(reverse("employers:thank_you")) # TODO: Add this URL and template
return HttpResponse("Your form has been successfully submitted.")
else:
employer_form = EmployerForm()
job_listing_form = JobListingForm()
context = {
"employer_form": employer_form,
"job_listing_form": job_listing_form,
}
return render(request, 'employers/submit_job_listing.html', context)
#
class ChoicesView(generic.list.BaseListView):
paginate_by = 25
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.object_list = None
self.term = None
def get(self, request, *args, **kwargs):
self.term = kwargs.get("term", request.GET.get("term", ""))
self.object_list = self.get_queryset()
context = self.get_context_data()
return JsonResponse(
{
"results": [
{"id": value, "text": name}
for value, name in context["object_list"]
],
"more": context["page_obj"].has_next(),
}
)
def get_queryset(self):
return [(value, name) for value, name in self.queryset if self.term.lower() in name.lower()]
class LocationChoicesView(ChoicesView):
queryset = COUNTRY_CITY_CHOICES
回溯:
Environment:
Request Method: GET
Request URL: http://127.0.0.1:8000/submit-job-listing/
Django Version: 3.1.2
Python Version: 3.8.3
Installed Applications:
['employers.apps.EmployersConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django_select2']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Template error:
In template /home/john/Documents/Django_projects/jobsforjuniorseu/Version_1/jobsforjuniorseu/employers/templates/employers/submit_job_listing.html, error at line 15
Reverse for 'location_choices' not found. 'location_choices' is not a valid view function or pattern name.
5 : {{ employer_form.media.css }}
6 : <style>
7 : input, select {width: 100%}
8 : </style>
9 : </head>
10 : <body>
11 : <h1>Submit a job listing</h1>
12 : <form method="post" enctype="multipart/form-data">
13 : {% csrf_token %}
14 : {{ job_listing_form }}
15 : {{ employer_form }}
16 : <input type="submit" value= "Submit">
17 : </form>
18 : <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
19 : {{ employer_form.media.js }}
20 : </body>
21 : </html>
22 :
Traceback (most recent call last):
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/core/handlers/base.py", line 179, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/john/Documents/Django_projects/jobsforjuniorseu/Version_1/jobsforjuniorseu/employers/views.py", line 88, in submitJobListing
return render(request, 'employers/submit_job_listing.html', context)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/shortcuts.py", line 19, in render
content = loader.render_to_string(template_name, context, request, using=using)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/template/loader.py", line 62, in render_to_string
return template.render(context, request)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/template/backends/django.py", line 61, in render
return self.template.render(context)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/template/base.py", line 170, in render
return self._render(context)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/template/base.py", line 162, in _render
return self.nodelist.render(context)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/template/base.py", line 938, in render
bit = node.render_annotated(context)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
return self.render(context)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/template/base.py", line 994, in render
return render_value_in_context(output, context)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/template/base.py", line 973, in render_value_in_context
value = str(value)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/utils/html.py", line 376, in <lambda>
klass.__str__ = lambda self: mark_safe(klass_str(self))
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/forms/forms.py", line 134, in __str__
return self.as_table()
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/forms/forms.py", line 272, in as_table
return self._html_output(
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/forms/forms.py", line 229, in _html_output
output.append(normal_row % {
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/utils/html.py", line 376, in <lambda>
klass.__str__ = lambda self: mark_safe(klass_str(self))
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/forms/boundfield.py", line 34, in __str__
return self.as_widget()
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/forms/boundfield.py", line 93, in as_widget
return widget.render(
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django_select2/forms.py", line 262, in render
output = super().render(*args, **kwargs)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/forms/widgets.py", line 241, in render
context = self.get_context(name, value, attrs)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/forms/widgets.py", line 678, in get_context
context = super().get_context(name, value, attrs)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/forms/widgets.py", line 638, in get_context
context = super().get_context(name, value, attrs)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/forms/widgets.py", line 234, in get_context
'attrs': self.build_attrs(self.attrs, attrs),
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django_select2/forms.py", line 240, in build_attrs
"data-ajax--url": self.get_url(),
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django_select2/forms.py", line 235, in get_url
return reverse(self.data_view)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/urls/base.py", line 87, in reverse
return iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs))
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/urls/resolvers.py", line 685, in _reverse_with_prefix
raise NoReverseMatch(msg)
Exception Type: NoReverseMatch at /submit-job-listing/
Exception Value: Reverse for 'location_choices' not found. 'location_choices' is not a valid view function or pattern name.
如方法名所示,get_queryset(...)
方法应该return一个 QuerySet
而在您的情况下,您正在 return 其他东西。
应该是这样的,
from django_select2 import forms as s2forms
class LocationWidget(s2forms.ModelSelect2Widget):
search_fields = [
"location__icontains",
]
<b>def get_queryset(self):
return Employer.objects.all()</b>
但是,我希望,在你的情况下,你不需要使用 get_queryset(...)
方法
更新 1
您的 .html
似乎遗漏了某些部分
<b>{{ form.media.css }}</b>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ employer_form.as_p }}
<input type="submit" value="Submit">
</form>
<b><script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
{{ form.media.js }}</b>
看来您只需要一个灯1 小部件。
如果 choices
是一个大型静态列表,那么您可能需要一个重量级的小部件。
灯光小部件
将LocationWidget
替换为s2forms.Select2Widget
。
forms.py:
EmployerForm = modelform_factory(
Employer,
fields=["name", "location", "short_bio", "website"],
widgets={"location": s2forms.Select2Widget})
重型小部件
而不是为 LocationWidget
继承 s2forms.ModelSelect2Widget
:
- 继承
s2forms.HeavySelect2Widget
并指定data_view
,以及
- 实现指定的视图。
forms.py:
from django.db.models.fields import BLANK_CHOICE_DASH
class LocationWidget(s2forms.HeavySelect2Widget):
data_view = "location_choices" # "employers:location_choices"
def __init__(self, attrs=None, choices=(), **kwargs):
super().__init__(attrs=attrs, choices=choices, data_view=self.data_view, **kwargs)
@property
def choices(self):
return BLANK_CHOICE_DASH # Avoid rendering all choices in HeavySelect2Widget
@choices.setter
def choices(self, value):
pass
urls.py:
# app_name = "employers"
urlpatterns = [
path('', views.submitEmployer, name='index'),
path('choices/location.json', LocationChoicesView.as_view(), name='location_choices'),
]
views.py:
class ChoicesView(BaseListView):
paginate_by = 25
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.object_list = None
self.term = None
def get(self, request, *args, **kwargs):
self.term = kwargs.get("term", request.GET.get("term", ""))
self.object_list = self.get_queryset()
context = self.get_context_data()
return JsonResponse(
{
"results": [
{"id": value, "text": name}
for value, name in context["object_list"]
],
"more": context["page_obj"].has_next(),
}
)
def get_queryset(self):
return [(value, name) for value, name in self.queryset if self.term.lower() in name.lower()]
class LocationChoicesView(ChoicesView):
queryset = COUNTRY_CITY_CHOICES
参考资料
我安装了 Django-Select2 并将其应用到我的项目中,但我遇到了一个无法解决的错误。
这是我的 forms.py
文件:
from django.forms import modelform_factory
from django_select2 import forms as s2forms
from .models import Employer, JobListing, Category_JobListing
class LocationWidget(s2forms.ModelSelect2Widget):
search_fields = [
"location__icontains",
]
def get_queryset(self):
return Employer._meta.get_field("location").choices
EmployerForm = modelform_factory(Employer, fields=["name", "location", "short_bio", "website", "profile_picture"], widgets={"location": LocationWidget})
views.py
文件(仅相关代码部分):
def submitJobListing(request):
if request.method == "POST":
employer_form = EmployerForm(request.POST, request.FILES)
employer = employer_form.save()
return HttpResponse("Your form has been successfully submitted.")
else:
employer_form = EmployerForm()
context = {
"employer_form": employer_form,
}
return render(request, 'employers/submit_job_listing.html', context)
submit_job_listing.html
(我的模板文件):
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ employer_form }}
<input type="submit" value= "Submit">
</form>
使用这段代码,我得到:
AttributeError at /submit-job-listing/
'list' object has no attribute 'none'
输出表明错误与模板中的 {{ employer_form }}
和视图中的 return render(request, 'employers/submit_job_listing.html', context)
有关。
我知道发生这个错误是因为我重写了LocationWidget
中的get_queryset()
方法,但我不知道我做错了什么。
这里有什么问题,我该如何解决?
更新 1:
我遇到一个问题 NoReverseMatch at /submit-job-listing/ Reverse for 'location_choices' not found. 'location_choices' is not a valid view function or pattern name.
。这很可能是我的整个项目中答案代码集成的问题。我不明白为什么会这样。当我收到错误消息时,我尝试访问的 URL 是 http://127.0.0.1:8000/submit-job-listing/
.
相关代码如下:
forms.py
:
from django.forms import modelform_factory
from django_select2 import forms as s2forms
from .models import Employer, JobListing, Category
from django import forms
class LocationWidget(s2forms.HeavySelect2Widget):
data_view = "location_choices"
def __init__(self, attrs=None, choices=(), **kwargs):
super().__init__(attrs=attrs, choices=choices, data_view=self.data_view, **kwargs)
EmployerForm = modelform_factory(Employer, fields=["name", "location", "short_bio", "website", "profile_picture"], widgets={"location": LocationWidget})
JobListingForm = modelform_factory(JobListing, fields=["job_title", "job_description", "job_requirements", "what_we_offer", "job_application_url", "categories"])
urls.py
:
from django.urls import path
from . import views
app_name = "employers"
urlpatterns = [
path("", views.ListJobListingsView.as_view(), name="list_joblistings"),
path("choices/location.json", views.LocationChoicesView.as_view(), name="location_choices"),
path("<int:pk>/", views.DetailJobListingView.as_view(), name="detail_joblisting"),
# path("employers/", views.IndexEmployersView.as_view(), name="index"),
path("employers/<int:pk>/", views.DetailEmployerView.as_view(), name="detail_employer"),
path("submit-job-listing/", views.submitJobListing, name="submit_job_listing"),
# path("submit-job-listing/success/", )
]
views.py
:
def submitJobListing(request):
if request.method == "POST":
employer_form = EmployerForm(request.POST, request.FILES)
job_listing_form = JobListingForm(request.POST, request.FILES)
#check if employer with that name already exists
employer_name = str(request.POST.get("name", ""))
employer_with_the_same_name = Employer.objects.get(name=employer_name)
employer = None
if (employer_with_the_same_name != None):
employer = employer_with_the_same_name
if employer == None and employer_form.is_valid() and job_listing_form.is_valid():
employer = employer_form.save()
job_listing = job_listing_form.save(commit=False)
job_listing.employer = employer
job_listing.save()
#return HttpResponseRedirect(reverse("employers:thank_you")) # TODO: Add this URL and template
return HttpResponse("Your form has been successfully submitted.")
else:
employer_form = EmployerForm()
job_listing_form = JobListingForm()
context = {
"employer_form": employer_form,
"job_listing_form": job_listing_form,
}
return render(request, 'employers/submit_job_listing.html', context)
#
class ChoicesView(generic.list.BaseListView):
paginate_by = 25
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.object_list = None
self.term = None
def get(self, request, *args, **kwargs):
self.term = kwargs.get("term", request.GET.get("term", ""))
self.object_list = self.get_queryset()
context = self.get_context_data()
return JsonResponse(
{
"results": [
{"id": value, "text": name}
for value, name in context["object_list"]
],
"more": context["page_obj"].has_next(),
}
)
def get_queryset(self):
return [(value, name) for value, name in self.queryset if self.term.lower() in name.lower()]
class LocationChoicesView(ChoicesView):
queryset = COUNTRY_CITY_CHOICES
回溯:
Environment:
Request Method: GET
Request URL: http://127.0.0.1:8000/submit-job-listing/
Django Version: 3.1.2
Python Version: 3.8.3
Installed Applications:
['employers.apps.EmployersConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django_select2']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Template error:
In template /home/john/Documents/Django_projects/jobsforjuniorseu/Version_1/jobsforjuniorseu/employers/templates/employers/submit_job_listing.html, error at line 15
Reverse for 'location_choices' not found. 'location_choices' is not a valid view function or pattern name.
5 : {{ employer_form.media.css }}
6 : <style>
7 : input, select {width: 100%}
8 : </style>
9 : </head>
10 : <body>
11 : <h1>Submit a job listing</h1>
12 : <form method="post" enctype="multipart/form-data">
13 : {% csrf_token %}
14 : {{ job_listing_form }}
15 : {{ employer_form }}
16 : <input type="submit" value= "Submit">
17 : </form>
18 : <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
19 : {{ employer_form.media.js }}
20 : </body>
21 : </html>
22 :
Traceback (most recent call last):
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/core/handlers/base.py", line 179, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/john/Documents/Django_projects/jobsforjuniorseu/Version_1/jobsforjuniorseu/employers/views.py", line 88, in submitJobListing
return render(request, 'employers/submit_job_listing.html', context)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/shortcuts.py", line 19, in render
content = loader.render_to_string(template_name, context, request, using=using)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/template/loader.py", line 62, in render_to_string
return template.render(context, request)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/template/backends/django.py", line 61, in render
return self.template.render(context)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/template/base.py", line 170, in render
return self._render(context)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/template/base.py", line 162, in _render
return self.nodelist.render(context)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/template/base.py", line 938, in render
bit = node.render_annotated(context)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
return self.render(context)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/template/base.py", line 994, in render
return render_value_in_context(output, context)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/template/base.py", line 973, in render_value_in_context
value = str(value)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/utils/html.py", line 376, in <lambda>
klass.__str__ = lambda self: mark_safe(klass_str(self))
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/forms/forms.py", line 134, in __str__
return self.as_table()
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/forms/forms.py", line 272, in as_table
return self._html_output(
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/forms/forms.py", line 229, in _html_output
output.append(normal_row % {
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/utils/html.py", line 376, in <lambda>
klass.__str__ = lambda self: mark_safe(klass_str(self))
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/forms/boundfield.py", line 34, in __str__
return self.as_widget()
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/forms/boundfield.py", line 93, in as_widget
return widget.render(
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django_select2/forms.py", line 262, in render
output = super().render(*args, **kwargs)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/forms/widgets.py", line 241, in render
context = self.get_context(name, value, attrs)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/forms/widgets.py", line 678, in get_context
context = super().get_context(name, value, attrs)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/forms/widgets.py", line 638, in get_context
context = super().get_context(name, value, attrs)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/forms/widgets.py", line 234, in get_context
'attrs': self.build_attrs(self.attrs, attrs),
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django_select2/forms.py", line 240, in build_attrs
"data-ajax--url": self.get_url(),
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django_select2/forms.py", line 235, in get_url
return reverse(self.data_view)
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/urls/base.py", line 87, in reverse
return iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs))
File "/home/john/anaconda3/envs/django/lib/python3.8/site-packages/django/urls/resolvers.py", line 685, in _reverse_with_prefix
raise NoReverseMatch(msg)
Exception Type: NoReverseMatch at /submit-job-listing/
Exception Value: Reverse for 'location_choices' not found. 'location_choices' is not a valid view function or pattern name.
如方法名所示,get_queryset(...)
方法应该return一个 QuerySet
而在您的情况下,您正在 return 其他东西。
应该是这样的,
from django_select2 import forms as s2forms
class LocationWidget(s2forms.ModelSelect2Widget):
search_fields = [
"location__icontains",
]
<b>def get_queryset(self):
return Employer.objects.all()</b>
但是,我希望,在你的情况下,你不需要使用 get_queryset(...)
方法
更新 1
您的 .html
似乎遗漏了某些部分<b>{{ form.media.css }}</b>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ employer_form.as_p }}
<input type="submit" value="Submit">
</form>
<b><script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
{{ form.media.js }}</b>
看来您只需要一个灯1 小部件。
如果 choices
是一个大型静态列表,那么您可能需要一个重量级的小部件。
灯光小部件
将LocationWidget
替换为s2forms.Select2Widget
。
forms.py:
EmployerForm = modelform_factory(
Employer,
fields=["name", "location", "short_bio", "website"],
widgets={"location": s2forms.Select2Widget})
重型小部件
而不是为 LocationWidget
继承 s2forms.ModelSelect2Widget
:
- 继承
s2forms.HeavySelect2Widget
并指定data_view
,以及 - 实现指定的视图。
forms.py:
from django.db.models.fields import BLANK_CHOICE_DASH
class LocationWidget(s2forms.HeavySelect2Widget):
data_view = "location_choices" # "employers:location_choices"
def __init__(self, attrs=None, choices=(), **kwargs):
super().__init__(attrs=attrs, choices=choices, data_view=self.data_view, **kwargs)
@property
def choices(self):
return BLANK_CHOICE_DASH # Avoid rendering all choices in HeavySelect2Widget
@choices.setter
def choices(self, value):
pass
urls.py:
# app_name = "employers"
urlpatterns = [
path('', views.submitEmployer, name='index'),
path('choices/location.json', LocationChoicesView.as_view(), name='location_choices'),
]
views.py:
class ChoicesView(BaseListView):
paginate_by = 25
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.object_list = None
self.term = None
def get(self, request, *args, **kwargs):
self.term = kwargs.get("term", request.GET.get("term", ""))
self.object_list = self.get_queryset()
context = self.get_context_data()
return JsonResponse(
{
"results": [
{"id": value, "text": name}
for value, name in context["object_list"]
],
"more": context["page_obj"].has_next(),
}
)
def get_queryset(self):
return [(value, name) for value, name in self.queryset if self.term.lower() in name.lower()]
class LocationChoicesView(ChoicesView):
queryset = COUNTRY_CITY_CHOICES