首页 > 解决方案 > 如何在 django 的 url 上放置搜索查询?

问题描述

我正在使用 Django 创建一个搜索应用程序。

我做了一个文章模型和一个记录文章评分的反馈模型。

进入搜索框并显示搜索结果后,单击其中一个结果,然后转到详细信息屏幕。

在详细屏幕上选择反馈并按下提交按钮后,我想将搜索查询保存到反馈模型。

我认为解决方案是在 URL 中添加一个查询portal/search/?=query并阅读它,但我不知道如何编码。另外,能否教教我URL中除了读取查询之外是否还有其他实现方法?

此外,当我从详细屏幕返回时,我也想显示以前的搜索结果。

如果您有任何问题,请发表评论。原谅我糟糕的英语。

模型.py

from django.db import models
from django.urls import reverse
from taggit.managers import TaggableManager

class KnowHow(models.Model):

    BASIC_TAGS =(
        ('1','one'),
        ('2','two'),
        ('3','three'),
        ('4','four'),
        ('5','five'),
        ('6','six'),
    )

    CATEGORY =(
        ('1','Type2'),
        ('2','Type1'),
    )


    author = models.ForeignKey('auth.User',on_delete=models.CASCADE)
    category = models.CharField(max_length=1,choices=CATEGORY,default='1')
    title = models.CharField(max_length=200)
    text = models.TextField(blank=True,default=' ')
    # delault=' ':import system will give a error if text column is null
    file = models.FileField(blank=True,upload_to='explicit_knowhows')
    basic_tag = models.CharField(max_length=1,choices=BASIC_TAGS,default='1')
    free_tags = TaggableManager(blank=True)

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('portal:index')


class Feedback(models.Model):

    EFFECT =(
        ('1','great'),
        ('2','maybe good'),
        ('3','bad'),
    )
    NOVEL =(
        ('1','I didn't know that'),
        ('2','I know, but I forgot'),
        ('3','I know this.'),
    )

    kh = models.ForeignKey(KnowHow, on_delete=models.PROTECT)
    user = models.ForeignKey('auth.User',on_delete=models.CASCADE)
    query = models.TextField(blank=True)
    time = models.DateTimeField(auto_now_add=True)
    efficacy = models.CharField(max_length=1,choices=EFFECT,default='1')
    novelty = models.CharField(max_length=1,choices=NOVEL,default='1')


    def __str__(self):
        return self.time.strftime("%Y/%m/%d %H:%M:%S")

视图.py

from django.urls import reverse, reverse_lazy
from django.http import HttpResponse
from django.views import generic
from django.views.generic.edit import ModelFormMixin
from django.shortcuts import redirect,get_object_or_404
from django.core.exceptions import PermissionDenied
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.decorators import login_required
from .models import KnowHow
from taggit.models import Tag
from .forms import SearchForm,FeedbackForm
from django.db.models import Q

"""
Django Auth
The LoginRequired mixin
https://docs.djangoproject.com/en/2.0/topics/auth/default/#the-loginrequired-mixin
The login_required decorator
https://docs.djangoproject.com/en/2.0/topics/auth/default/#the-login-required-decorator
@login_required
"""


class IndexView(LoginRequiredMixin,generic.list.ListView):
    model = KnowHow
    #paginate_by = 5
    ordering = ['-title']
    # template_name = 'portal/KnowHow_list.html'


class DetailView(ModelFormMixin,LoginRequiredMixin,generic.detail.DetailView):
    # from https://torina.top/detail/337/
    model = KnowHow
    form_class = FeedbackForm
    template_name = 'portal/KnowHow_detail.html'

    def form_valid(self, form):
        kh_pk = self.kwargs['pk']
        Feedback = form.save(commit=False)
        Feedback.kh = get_object_or_404(KnowHow, pk=kh_pk)
        Feedback.query=""
        Feedback.user=self.request.user
        Feedback.save()
        return redirect('portal:search')

    def post(self, request, *args, **kwargs):
        form = self.get_form()
        if form.is_valid():
            return self.form_valid(form)
        else:
            self.object = self.get_object()
            return self.form_invalid(form)


class CreateView(LoginRequiredMixin, generic.edit.CreateView):  # The LoginRequired mixin
    model = KnowHow
    fields = ['category','title','text','file','basic_tag','free_tags'] 

    #template_name = 'portal/KnowHow_form.html'
    def form_valid(self, form):
        # This method is called when valid form data has been posted.
        # It should return an HttpResponse.
        # https://docs.djangoproject.com/en/2.0/topics/class-based-views/generic-editing/#models-and-request-user
        form.instance.author = self.request.user
        return super(CreateView, self).form_valid(form)


class UpdateView(LoginRequiredMixin, generic.edit.UpdateView):  # The LoginRequired mixin
    model = KnowHow
    fields = ['category','title','text','file','basic_tag','free_tags']

    #template_name = 'portal/KnowHow_form.html'




class DeleteView(LoginRequiredMixin, generic.edit.DeleteView):  # The LoginRequired mixin
    model = KnowHow
    success_url = reverse_lazy('portal:index')

    def delete(self, request, *args, **kwargs):
        result = super().delete(request, *args, **kwargs)
        Tag.objects.filter(knowhow=None).delete()
        return result
    #template_name = 'portal/KnowHow_confirm_delete.html'

class SearchIndexView(LoginRequiredMixin, generic.ListView):

    template_name="search/search_index.html"
    model = KnowHow

    def post(self, request, *args, **kwargs):

        form_value = [
            self.request.POST.get('basic_tag', None),
            self.request.POST.get('free_tags', None),
        ]
        request.session['form_value'] = form_value

        self.request.GET = self.request.GET.copy()
        self.request.GET.clear()

        return self.get(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        basic_tag = ''
        free_tags = ''
        if 'form_value' in self.request.session:
            form_value = self.request.session['form_value']
            basic_tag = form_value[0]
            free_tags = form_value[1]

        default_data = {'basic_tag': basic_tag,
                        'free_tags': free_tags,
                        }

        test_form = SearchForm(initial=default_data)
        context['test_form'] = test_form

        return context

    def get_queryset(self):

        if 'form_value' in self.request.session:
            form_value = self.request.session['form_value']
            basic_tag = form_value[0]
            free_tags = form_value[1]

            condition_basic_tag = Q()
            condition_free_tags = Q()

            if len(basic_tag) != 0 and basic_tag[0]:
                condition_basic_tag = Q(basic_tag=basic_tag)
            if len(free_tags) != 0 and free_tags[0]:
                condition_free_tags = Q(free_tags__name__in=free_tags)

            return KnowHow.objects.filter(condition_basic_tag & condition_free_tags).distinct()
        else:
            return KnowHow.objects.none()


@login_required
def help(request):
    return HttpResponse("Member Only Help Page")

网址.py

from django.urls import path

from . import views
# set the application namespace
# https://docs.djangoproject.com/en/2.0/intro/tutorial03/
app_name = 'portal'

urlpatterns = [
    # ex: /
    path('', views.IndexView.as_view(), name='index'),

    # ex: /KnowHow/create/
    path('KnowHow/create/', views.CreateView.as_view(), name='create'),

    # ex: /KnowHow/1/
    path('KnowHow/<int:pk>/detail/', views.DetailView.as_view(), name='detail'),

    # ex: /KnowHow/1/update/
    path('KnowHow/<int:pk>/update/', views.UpdateView.as_view(), name='update'),

    # ex: /KnowHow/1/delete
    path('KnowHow/<int:pk>/delete/', views.DeleteView.as_view(), name='delete'),

    # ex: /KnowHow/help/
    path('KnowHow/help/', views.help, name='help'),

    path('search/',views.SearchIndexView.as_view(), name='search')
]

标签: pythondjangopython-3.xsearch

解决方案


您的问题有几种解决方案。

  1. 第一个是您自己提到的确切解决方案。使用查询字符串参数,例如?q=详细KnowHow信息视图。
  2. 使用SearchLog模型并使用该模型的标识符。当有人点击/search/端点时,您创建一个新SearchLog的并将pk此记录传递到您的前面。基本上它就像?q=选项一样。相反,您可以使用?search_id=将反馈绑定到特定的SearchLog
  3. 使用用户会话。将搜索到的查询绑定到用户的会话,当他们想要创建一个新Feedback的时,query在他们的会话中使用。

对于前两个选项,您只需要正确创建详细链接的网址(在您的搜索结果页面中)。在您的模板中,执行以下操作:

# You are probably doing something like this
{% for r in results %}
<a href="{{r.absolute_url}}">{{r.name}}</a>
{% endfor %}

# You should do this instead
{% for r in results %}
<a href="{{r.absolute_url}}{{current_query}}">{{r.name}}</a>
{% endfor %}

您可以在渲染模板时传入current_querycontext的值,也可以使用 javascript 从浏览器的location / query string.


推荐阅读