【问题标题】:Django Search Implementation, conditional routingDjango 搜索实现,条件路由
【发布时间】:2020-12-02 06:01:24
【问题描述】:

我正在尝试使用 Django 实现基本的搜索功能。可以使用帮助来访问基于功能或基于类的视图中模板中的表单的查询输入。预期功能:

  • 如果存在确切的搜索查询页面,则显示该页面
  • 如果页面标题包含查询的内容,则显示所有结果
  • 如果两者都没有,则显示一条消息,说明未找到结果

我只是在学习,所以我尝试了功能视图和基于类的视图。我在文档/视频/教科书上花了很长时间,但不知道如何从基于类的视图中获得预期的行为。我了解收集 object_list 并获取 query_set,但是您如何路由到这三个不同的条件。我尝试覆盖 dispatch() 和 as_views() 方法无济于事。尝试使用 Django 表单类,但没有。

由于某种原因,功能视图会继续执行第一个 try 语句,而不是在未找到完全匹配时抛出 DoesNotExist 异常。所以它显示的是入口页面而不是搜索结果页面。看起来 request.GET 无论如何都是 None 类型,因为当我尝试打印时什么都没有显示。

urls.py

from re import search
from django.urls import path

from . import views
from .views import IndexPageView, SearchView

app_name = "wiki"
urlpatterns = [
    # ex: /wiki/
    path("", views.index, name="index"),
    # path("", IndexPageView.as_view(), name="index"),
    # ex: /wiki/EntryPageName
    path("wiki/<str:entry>/", views.displayEntry, name="displayEntry"),
    # path("wiki/search/", views.searchView, name="searchView")
    path("wiki/search/", SearchView.as_view(), name="searchView")
]

型号

class Entry(models.Model):
    title = models.CharField(max_length=64)
    def __str__(self):
        return f"{self.title}"
    content = models.TextField()

views.py

def searchView(request):
    searchedTerm = request.GET.get('q')
    try:
        exactMatch = Entry.objects.get(title=searchedTerm)
        entryTitle = exactMatch.title
        entryHTML = markdown2.markdown(exactMatch.content)
        return render(request, "encyclopedia/displayEntry.html", {
            "entryTitle": entryTitle,
            "entryHTML": entryHTML
        })
    except:
        try:
            searchResults = Entry.objects.filter(Q(title__icontains=searchedTerm))
            return render(request, "encyclopedia/searchResults.html", {
                "searchResults": searchResults,
                "searchedTerm": searchedTerm
            })
        except:
            return render(request, "encyclopedia/searchResults.html", {
            "emptyResults": f"No entries found matching: {searchedTerm}",
            "searchedTerm": searchedTerm
        })

class SearchView(ListView):
    template_name = "encyclopedia/searchResults.html"
    model = Entry
    context_object_name = "searchList"

    def get_queryset(self):
        searchedTerm = self.request.GET.get('q')
        try:
            searchResults = Entry.objects.get(title=searchedTerm)
            return searchResults
        except:
            try:
                searchResults = Entry.objects.filter(Q(title__icontains=searchedTerm))
                return searchResults
            except:
                pass
            
    def as_view():
        searchedTerm = self.request.GET.get('q')
        try:
            exactMatch = Entry.objects.get(title=searchedTerm)
            entryTitle = exactMatch.title
            entryHTML = markdown2.markdown(exactMatch.content)
            return render(request, "encyclopedia/displayEntry.html", {
                "entryTitle": entryTitle,
                "entryHTML": entryHTML,
            })
        except:
            searchResults = Entry.objects.filter(Q(title__icontains=searchedTerm))
            return render(request, "encyclopedia/searchResults.html", {
                "searchResults": searchResults,
                "searchedTerm": searchedTerm
            })
        else:
            return render(request, "encyclopedia/searchResults.html", {
                "emptyResults": f"No entries found matching: {searchedTerm}",
                "searchedTerm": searchedTerm
            })

从 layout.html 搜索表单

<form action="{% url 'wiki:search' %}" method="GET">
    <input class="search" type="text" name="q" placeholder="Search Encyclopedia">
    <!-- <input type="submit" value="submit"> -->
</form>

显示入口页面模板

{% extends "encyclopedia/layout.html" %}

{% block title %}
    {% if entryTitle %}
        {{ entryTitle }}
    {% else %}
        Page Not Found!
    {% endif %}
{% endblock %}

{% block body %}
    {% if entryHTML %}
        {{ entryHTML|safe }}
    {% else %}
        <p>This page does not exist yet.</p>
        <p>Check your spelling or create a new entry!</p>
        <p>?? {{ testPrint }}</p>
    {% endif %}
{% endblock %}

搜索结果页面

{% extends "encyclopedia/layout.html" %}

{% block title %}
    Search Results: {{ searchedTerm }}
{% endblock %}


{% block body %}

    {% if searchResults %}
        <h3>Search Results</h3>
        <ul>
            {% for result in searchResults %}    
                <li><a href="{% url 'wiki:displayPage' result.title %}">{{ result.title }}</a></li>
            {% endfor %}
        </ul>
    {% else %}
        <h3>{{ emptyResults }}</h3>        
    {% endif %}

{% endblock %}

【问题讨论】:

    标签: django django-models django-views


    【解决方案1】:

    型号

    class Entry(models.Model):
       title = models.CharField(max_length=64)
       content = models.TextField()
    
       def __str__(self):
         return self.title
    

    观看次数

    from django.views.generic.list import ListView
    from django.views.generic.detail import DetailView
    from app.models import Entry
    
    class EntryListView(ListView):
    
       model = Entry
       paginate_by = 100  # if pagination is desired
    
       def get_queryset(self):
         queryset = super().get_queryset()
         q = self.request.GET.get("q")
         if q:
            queryset = queryset.filter(title__icontains=q)
         return queryset
    
    
     class EntryDetailView(DetailView):
        model = Entry
    

    网址

    from django.urls import path
    
    from app.views import EntryListView, EntryDetailView
    
    urlpatterns = [
        path('', EntryListView.as_view(), name='entry-list'),
        path('<int:pk>/', ArticleDetailView.as_view(), name='entry-detail'),
    ]
    

    【讨论】:

    • 你能解释一下 get_queryset 覆盖发生了什么吗?另外,它怎么知道如何直接进入一个条目的页面或搜索结果页面
    • 搜索表单在列表视图模板中,那么每个实体都有一个单独的 url
    • 谢谢,我没有完全理解基于类的视图。对于任何想知道的人,这个视频对解释它最有帮助:youtube.com/watch?v=F5mRW0jo-U4&t=8720s
    猜你喜欢
    • 2022-08-17
    • 2020-12-02
    • 1970-01-01
    • 2018-11-10
    • 1970-01-01
    • 2023-03-17
    • 2019-09-19
    • 2012-01-28
    • 2020-05-06
    相关资源
    最近更新 更多