質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.59%

Dajango2.2で検索クエリをurlに引き継ぎたい。

受付中

回答 0

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 429

Spacekoki

score 13

djangoで検索アプリケーションを作成しています。
この記事を参考に作りました。
また,記事への評価を記録するFeedbackモデルを追加しました。
検索をし,検索結果を表示させた後,記事をクリックすると詳細画面に移行するようにしています。
詳細画面にてフィードバックを入力して送信ボタンを押した後に検索式(クエリ)をモデルに保存したいのですが,どうすればよいのでしょうか。クエリをurlに持たせてそれを読み込むのがよいのかなと持っていますが,実装方法がわかりません。また,urlに持たせる以外のの実装方法があるなら教えていただけると幸いです。
イメージとしてはportal/search/?q=検索ワードみたいな感じ。
また,詳細画面から戻ったときに前の検索結果を表示させたいのですが,実装方法を教えていたけると幸いです。
どちらかでもわかった方がいらっしゃいましたら回答して抱変えると嬉しいです。
何か質問がありましたらコメントをください。

以下,models.py,views.py,urls.py
models.py

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

class KnowHow(models.Model):

    BASIC_TAGS =(
        ('1','資料作成(スライド・ポスター)'),
        ('2','資料作成(論文・要旨)'),
        ('3','開発'),
        ('4','実験・考察'),
        ('5','用語の定義・説明'),
        ('6','プレゼンテーション'),
    )

    CATEGORY =(
        ('1','暗黙的ノウハウ'),
        ('2','形式的ノウハウ'),
    )


    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','役立ちそう'),
        ('2','後々,役立ちそう'),
        ('3','役に立ちそうにない'),
    )
    NOVEL =(
        ('1','知らない内容だった'),
        ('2','知っていたが忘れていた'),
        ('3','既に知っている内容だった'),
    )

    kh = models.ForeignKey(KnowHow, verbose_name='紐づくノウハウ', 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.query


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):

        # sessionに値がある場合、その値でクエリ発行する。
        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')
]
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

まだ回答がついていません

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る