【问题标题】:Making a proper search function in Django在 Django 中制作适当的搜索功能
【发布时间】:2017-12-02 06:55:39
【问题描述】:

我正在尝试创建一个搜索功能,允许我在实例中输入对象的值,以便我可以在与搜索页面相同的页面上显示该实例及其中的几个对象。到目前为止,这是我所拥有的:

#models.py

class Student(models.Model):
    # STEP 1 BASIC INFO
    student_id = models.CharField(max_length=128, unique=True)
    first_name = models.CharField(max_length=128)
    last_name = models.CharField(max_length=128)
    ssn = USSocialSecurityNumberField(null=False)
    gender = models.CharField(max_length=128, choices=GENDER_CHOICES)
    dob = models.DateField(auto_now=False, auto_now_add=False, db_column="date of birth")
    contact_number = models.CharField(max_length=128)
    address = models.CharField(max_length=128)
    city = models.CharField(max_length=128)
    state = USStateField(choices=STATE_CHOICES, default='NJ')
    zipcode = USZipCodeField(blank=True)
    country = CountryField(default='US', blank=True)
    home_phone = models.CharField(max_length=128)
    cell_phone = models.CharField(max_length=128)
    email = models.EmailField(max_length=254, validators=[validate_email])

    def __str__(self):
        return self.first_name + self.last_name

#views.py

def search_Student(request):
    context_dict = {}
    if request.method == 'POST':
        query = request.POST['last_name_search']
        results = Student.objects.filter(last_name=query)
        if query:
            context_dict['results'] = results
        else:
            context_dict['no_results'] = query
    return render(request, "students/search_student.html", context_dict)

#search_student.html

{% block main_content %}
<form method="post" action="/students/search_student/">
    {% csrf_token %}
    <label for="last_name_search">Last Name:</label>
    <input type="text" name="last_name_search" id="last_name_search">
    <input type="submit" name="submit">
</form>
<div id="result_panel">
    {% if no_results %}
        No results returned for <q>{{ no_results }}</q>
    {% else %}
        {% for result in results %}
            {{ result.last_name }}
        {% endfor %}
    {% endif %}
</div>
{% endblock %}

#urls.py

urlpatterns = [
    url(r'^$', students_views.Students, name='students'),
    url(r'^add_student/$', students_views.add_Student, name='add_student'),
    url(r'^id=(?P<identify>[\w]+)/add_studentcourse/$', students_views.add_StudentCourse, name='add_studentcourse'),
    url(r'^id=(?P<identify>[\w]+)/add_studentemployment/$', students_views.add_StudentEmployment, name='add_studentemployment'),
    url(r'test/$', students_views.test, name='test'),
    #URL for the search page.
    url(r'^search_student/$', students_views.search_Student, name='search_student'),
    url(r'^current_student/$', students_views.current_Student, name='current_student'),
    url(r'^all_my_student/$', students_views.all_My_Student, name='all_my_student'),
    url(r'^public_student/$', students_views.public_Student, name='public_student'),
    url(r'^sales_reports/$', students_views.sales_Reports, name='sales_reports'),
    url(r'^switch_counselor/$', students_views.switch_Counselor, name='switch_counselor'),
    url(r'^source_admin/$', students_views.source_Admin, name='source_admin'),
    url(r'^super_tool/$', students_views.super_Tool, name='super_tool'),
    url(r'^help_and_settings/$', students_views.help_And_Settings, name='help_and_settings'),
]

基本上,如果我在输入中输入姓氏,我希望它能够获取所有具有相同姓氏的模型实例,并且能够放置我想要的关于所有匹配的任何信息实例,例如与搜索完全相同的页面上的姓名、性别和地址。 POST 方法可能令人困惑,但有人坚持我这样做(当我将方法更改为 GET 时它也不起作用)。有人可以指出我的代码中的任何错误或缺失的部分吗?谢谢。

编辑:添加了 urls.py。

【问题讨论】:

  • 第一个错误是您正在从您的视图中发送一个 dict 并试图将其视为模板中的列表。
  • 能把你遇到的错误说一下吗?
  • @ArpitSolanki 考虑到一堆匹配的结果,它不应该是一个列表吗?
  • 查看此行context_dict['results'] = results 此行生成一个字典,您将 context_dict 传递给您的模板。您应该只传递从过滤器查询中收到的结果,而不是使其成为字典
  • 您可以从表单标签中删除该操作吗?并添加您的 urls.py。我认为我们在这里的 url 和视图不匹配。

标签: django search


【解决方案1】:

所以我还不会让我发表评论,所以在这里说你确实可以(并且应该)将 dicts 视为 django 模板中的列表seen here.

你能发布你的错误吗?我不确定我看到了什么问题。你的方法很好地适应了我的代码,所以我有点迷茫。

格式编辑:

你也许应该制作一个编译时字典,IE:

context_dict = {
    "results": results
}
return render(request, "students/search_student.html", context_dict)

确保在 if 中返回,因此范围在正确的位置,如果您的 if 没有找到任何内容,则返回一个变量。

如果您坚持自己的答案,请尝试在模板中这样引用它..

{% for result in results.results %}

您的字典有一个结果条目,它指向变量结果。我相信您正在遍历当前示例中的字典,而不是所有查询。

【讨论】:

  • 控制台中没有可见的错误。点击搜索按钮后,结果将不会发布在搜索页面中。在这种情况下,搜索页面将不会显示被过滤的实例的姓氏。
  • 有几件事要看,应用程序是否在 settings.py 中注册?有什么信息可以实际查询吗?如果两者都是,只是为了缩小范围,我会遵循 Shockwave Moto 的建议,除了你的返回需要在 if 语句中发生,如果你没有找到查询,那么返回一个页面说它什么也没找到。或具有相同消息的变量。
【解决方案2】:

当然你可以使用查看方法,尝试在你的自定义搜索和模板代码中找到错误。

或者你可以用更 Django 的方式来做,依赖于 Django 的预构建功能:

使用 Django 的ListView 来查询和显示学生模型对象。您可以免费获得分页、错误处理和上下文设置。查看其他 StackOverflow 问题,例如 https://stackoverflow.com/a/33350839/621690 示例代码。

过滤学生的代码将进入get_queryset - 或者您可以使用django-filter

为了更好的可用性,您可以将 Select2 添加到您的表单输入中,它允许自动完成/前瞻。见django-select2

【讨论】:

    【解决方案3】:

    如何调试

    1. 从标签中删除操作。浏览器将自动发布到相同的 URL。这排除了重定向、映射或上游 urlconfs 的任何问题。
    2. 在浏览器中使用View Source 确保不返回任何内容,而不是 div 被 CSS 或 JS 隐藏。
    3. 确保找到结果:

    views.py

    if query:
        results = Student.objects.filter(last_name=query)
        if results.count():
            context_dict['results'] = results
        else:
            context_dict['no_results'] = query
    

    模板

    <div id="result_panel">
        {% if no_results %}
            No results returned for <q>{{ no_results }}</q>
        {% else %}
            {% for result in results %}
                {{ result.last_name }}
           {% endfor %}
        {% endif %}
    </div>
    

    请注意,以上内容不能为空。它应该总是显示一些东西。如果没有,那就是显示错误,数据在那里。见第 2 点。

    如果显示“无结果”部分,则尝试在 django shell 中复制查询:

    python manage.py shell
    >>> from yourapp.models import Student
    >>> Student.objects.filter(last_name='what you typed')
    >>> Student.objects.filter(last_name__iexact='what you typed')
    >>> Student.objects.filter(last_name__icontains='what you typed')
    >>> Student.objects.count()
    

    如果前三个都没有返回结果,那么你打错了或者数字 4 会显示你没有学生。

    【讨论】:

    • 带有 context_dict['no_results'] = last_name 的行令人困惑,因为 last_name 被视为错误。
    • 我的错,修复。固定的。而你击中它的事实说明了很多:)
    • 我的搜索页面仍然没有显示结果。我的视图的其余部分应该是什么样子?我是否应该将方法更改为 GET,因为有人告诉我不应该这样做。
    • 对不起,我想我应该吃点东西。现在真正修复了代码。
    • 我按照您在我的问题中所说的方式更改了它。还是不行。
    猜你喜欢
    • 2019-04-15
    • 1970-01-01
    • 2019-04-21
    • 1970-01-01
    • 2016-10-07
    • 2015-10-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多