我的Profile
模型在另一个模型ManyToManyField
上有一个Specialty
。
我希望对Profile
模型进行简单搜索,以反对专业并返回匹配的配置文件。目前,我的表单在我的模板中正确显示,但在提交后我无法获得任何内容。
models.py
:
from django.db import models
from django.conf import settings
class Specialty(models.Model):
title = models.CharField(max_length=255)
class Meta:
verbose_name_plural = 'Specialties'
def __unicode__(self):
return u"%s" % self.title
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
specialties = models.ManyToManyField(Specialty, blank=True)
def __unicode__(self):
return u"%s" % (self.user.username)
def get_absolute_url(self):
return reverse("profile_detail", args=[str(self.user.username)])
forms.py
:
from django import forms
from .profiles.models import Profile, Specialty
class ProfileSearchForm(forms.ModelForm):
specialty = forms.ModelMultipleChoiceField(queryset=Specialty.objects.all(), widget=forms.CheckboxSelectMultiple, required=False)
class Meta:
model = Profile
fields = ('specialty',)
views.py
:
from django.views.generic.edit import FormView
from django.core.urlresolvers import reverse_lazy
from .forms import ProfileSearchForm
from .profiles.models import Profile
class IndexView(FormView):
template_name = 'index.html'
form_class = ProfileSearchForm
success_url = reverse_lazy('index')
def form_valid(self, form):
specialty = form.cleaned_data['specialty']
self.profile_list = Profile.objects.filter(specialty__in=specialty)
return super(IndexView, self).form_valid(form)
index.html
:
<form action="{% url 'index' %}" method="get">
{{ form.as_p }}
<p><input type="submit" value="Search"></p>
</form>
<ul>
{% for profile in profile_list %}
<li><a href="{{ profile.get_absolute_url }}">{{ profile.user.get_full_name }}</a></li>
{% endfor %}
</ul>
我觉得它与self.profile_list
有关。我不知道是否应该如何进入get_extra_context
。它不会在第一次访问时存在,所以我不知道如何使其存在或传递它。我也不确定Profile.objects.filter(specialty__in=specialty)
是否是在多对多字段上进行字段查找的正确方法。
如果他们有优势,我也会对Haystack等其他搜索建议持开放态度。我更喜欢一组复选框,我不认为Haystack可以通过刻面来处理。
答案 0 :(得分:1)
谢谢,Gergo和Cameron。我现在修好了。你对这个问题是正确的,但还有很多步骤要做。
ListView
以及进行简单搜索的功能,该搜索应该是FormMixin
,可让我添加form_class
和success_url
,而不是全部为FormView
。model
中指定了默认ListView
,则视图会消除上下文,因此form
永远不会到达模板。 get_context_data
需要将表单添加回上下文,其中包含文档have an example。form_valid
应该被删除,因为搜索永远不是POST请求,尽管文档在FormMixin
中需要form_valid
和form_invalid
的“注释”中说明了这一点。 / LI>
get_queryset
才能通过model
获取默认查询集,或者阅读GET请求的specialties
值并相应地过滤结果。get_form_kwargs
需要将当前请求传递给表单,以便在页面刷新后保留初始表单值。棘手的部分是,在使用ModelMultipleChoiceField
时,您必须使用request.GET
的getlist
而非get
方法来阅读该值列表。现在一起......
forms.py
:
from django import forms
from .profiles.models import Profile, Specialty
class ProfileSearchForm(forms.ModelForm):
specialties = forms.ModelMultipleChoiceField(queryset=Specialty.objects.all(), widget=forms.CheckboxSelectMultiple, required=False)
class Meta:
model = Profile
fields = ('specialties',)
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request')
super(ProfileSearchForm, self).__init__(*args, **kwargs)
self.fields['specialties'].initial = self.request.GET.getlist('specialties')
views.py
:
from django.views.generic import ListView
from django.views.generic.edit import FormMixin
from django.core.urlresolvers import reverse_lazy
from .profiles.models import Profile
from .forms import ProfileSearchForm
class IndexView(FormMixin, ListView):
model = Profile
template_name = 'index.html'
form_class = ProfileSearchForm
success_url = reverse_lazy('index')
def get_queryset(self):
queryset = super(IndexView, self).get_queryset()
specialties = self.request.GET.getlist('specialties')
if specialties:
queryset = queryset.filter(specialties__in=specialties).distinct('user')
return queryset
def get_form_kwargs(self):
kwargs = super(IndexView, self).get_form_kwargs()
kwargs['request'] = self.request
return kwargs
def get_context_data(self, **kwargs):
context = super(IndexView, self).get_context_data(**kwargs)
form_class = self.get_form_class()
context['form'] = self.get_form(form_class)
return context
答案 1 :(得分:0)
我认为你正在寻找Profile.objects.filter(specialties__in=specialty)
- 个人资料没有专业领域,它有专业领域。