【问题标题】:How to place search query on url on django?如何在 django 的 url 上放置搜索查询?
【发布时间】:2020-01-05 14:29:19
【问题描述】:

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

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

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

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

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

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

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

models.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")

views.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")

urls.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')
]

【问题讨论】:

    标签: python django python-3.x search


    【解决方案1】:

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

    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 %}
    

    您可以在渲染模板时在context 中传递current_query,或者使用javascript 从浏览器的location / query string 中获取该值。

    【讨论】:

    • 我确实喜欢这个,但它没有用。 &lt;a href="{% url 'portal:detail' KnowHow.pk %}{{current_query}}"&gt;{{ KnowHow.title }}&lt;/a&gt;如何获取当前查询?
    • 您是否正确地将current_query 添加到您的SearchIndexView.get_context_data 中?
    • 嗯,对不起,我不知道该怎么做。
    • 您要保留的参数名称是什么?
    • basic_tag 和 free_tags。
    【解决方案2】:

    我将 SearchIndexView 中的 get_context_data 函数更改为: 在 return 前的最后一行添加这两行

    context['basic_tag'] = basic_tag
    context['free_tags'] = free_tags
    

    我也改了html。

    <a href="{% url 'portal:detail' KnowHow.pk %}{{current_query}}">{{ KnowHow.title }}</a>
    

    谢谢,@n1ma

    【讨论】:

      猜你喜欢
      • 2022-01-16
      • 2023-03-03
      • 1970-01-01
      • 2018-02-18
      • 1970-01-01
      • 2018-12-02
      • 2011-07-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多