前提
Windows11
Django4
Pyhton3.11
実現したいこと
1.検索フォームの作成
1)食品名を検索窓へ入力して検索ボタンをクリック。あいまい検索です。
2)検索結果の食品が検索ページと同じページ内(post_photo.html )に一覧で表示されるようにしたい。
Djangoを使ってWebサービスを開発しております。
下記サイトを参考に検索フォームを実装しようとしているのですが、検索窓がHTMLに組み込まれません。
ネットや書籍で検索フォームの作成について調べたのですがうまくできませんでした。
<参考にしているサイト>
12.Djangoに検索フォームを追加してみよう
https://denno-sekai.com/django-searchform/
<参考書籍>
Django4 Webアプリ開発実装ハンドブック--秀和システム
初めての質問で、要領を得ていなくて大変申し訳ないのですが、何卒よろしくお願い申し上げます。
発生している問題・エラーメッセージ
検索ボタン、検索窓が表示されない
該当のソースコード
※base.htmlについては文字数制限のため記載できなかったため、コメントを頂いた yuma.inaura 様への返信欄へ書かせていただきました。
**_HTML_** post_photo.html {% extends 'base.html' %} {% block title %}Post{% endblock %} {% block search %} <h1>食品検索</h1> {% if searchForm %}<!-- searchFormがあれば --> <form action='{% url "photo:SearchView" %}' method="get"><!-- getメソッドでインデックス関数を呼び出す --> <div> {{ searchForm }}<!-- views.pyから受け取ったsearchFormを表示 --> <input type="submit" value="検索"> <a href='{% url "photo:SearchView" %}'>クリア</a><!-- postメソッドでインデックス関数を呼び出す --> </div> </form> {% endif %} {% for article in articles %} <p> {{ article.user_name }} </p> {% endfor %} {% endblock %} {% block contents %} <hr> <!-- Bootstrapのグリッドシステム --> <br> <div class="container"> <!-- 行を配置 --> <div class="row"> <div class="col offset-2"> <form method="POST" enctype="multipart/form-data"> {% csrf_token %} <table> <tr> <th>カテゴリ</th> <td>{{ form.category }}</td> </tr> <tr> <th>タイトル</th> <td>{{ form.title }}</td> </tr> <tr> <th>コメント</th> <td>{{ form.comment }}</td> </tr> <tr> <th>材料・分量(g)</th> <td>{{ form.foodandweight }}</td> </tr> <tr> <th>人数</th> <td>{{ form.ninzu }}</td> </tr> <th>つくりかた</th> <td>{{ form.howtomake }}</td> </tr> <tr> <th>画像1</th> <td>{{ form.image1 }}</td> </tr> <tr> <th>画像2</th> <td>{{ form.image2 }}</td> </tr> </table> <hr> <button type="submit">投稿する</button> </form> </dv> </dv> </dv> {% endblock %} **_Python Django_** **_models.py_** class FoodListVer8(models.Model): id = models.IntegerField("通番",primary_key=True) foodname = models.TextField("食品名") **_forms.py_** from django.forms import ModelForm from .models import PhotoPost from django import forms class PhotoPostForm(ModelForm): class Meta: model = PhotoPost fields = ['category', 'title', 'comment', 'foodandweight','ninzu', 'howtomake', 'image1', 'image2'] # SearchFormクラスを定義 class SearchForm(forms.Form): keyword = forms.CharField(label='', max_length=50) **_views.py_** from django.shortcuts import render,get_object_or_404 from django.views.generic import TemplateView, ListView from django.views.generic import CreateView from django.urls import reverse_lazy from .forms import PhotoPostForm, SearchForm from django.utils.decorators import method_decorator from django.contrib.auth.decorators import login_required from .models import PhotoPost,FoodListVer8 from django.views.generic import DetailView from django.views.generic import DeleteView from django.http import HttpResponse # 検索用ビュー def SearchView(request): searchForm = SearchForm(request.GET) # searchForm変数に正常なデータがあれば if searchForm.is_valid(): keyword = searchForm.cleaned_data['keyword'] articles = FoodListVer8.objects.filter(foodname__contains=keyword) # それ以外の場合 else: searchForm = SearchForm() # searchForm変数をSearchFormオブジェクトで上書き articles = FoodListVer8.objects.all() # すべてのレコードを取得 context = { 'articles': articles, 'searchForm': searchForm, # テンプレートに渡すために追記 } return render(request, 'post_photo.html', context) def detail(request, id): article = get_object_or_404(FoodListVer8, pk=id) context = { 'article': article, } return render(request, 'post_photo.html', context) class IndexView(ListView): '''トップページのビュー ''' # index.htmlをレンダリングする template_name ='index.html' # モデルBlogPostのオブジェクトにorder_by()を適用して # 投稿日時の降順で並べ替える queryset = PhotoPost.objects.order_by('-posted_at') # 1ページに表示するレコードの件数 paginate_by = 9 @method_decorator(login_required, name='dispatch') class CreatePhotoView(CreateView): '''写真投稿ページのビュー # forms.pyのPhotoPostFormをフォームクラスとして登録 form_class = PhotoPostForm # レンダリングするテンプレート template_name = "post_photo.html" # フォームデータ登録完了後のリダイレクト先 success_url = reverse_lazy('photo:post_done') def form_valid(self, form): '''CreateViewクラスのform_valid()をオーバーライド フォームのバリデーションを通過したときに呼ばれる フォームデータの登録をここで行う parameters: form(django.forms.Form): form_classに格納されているPhotoPostFormオブジェクト Return: HttpResponseRedirectオブジェクト: スーパークラスのform_valid()の戻り値を返すことで、 success_urlで設定されているURLにリダイレクトさせる ''' # commit=FalseにしてPOSTされたデータを取得 postdata = form.save(commit=False) # 投稿ユーザーのidを取得してモデルのuserフィールドに格納 postdata.user = self.request.user # 投稿データをデータベースに登録 postdata.save() # 戻り値はスーパークラスのform_valid()の戻り値(HttpResponseRedirect) return super().form_valid(form) class PostSuccessView(TemplateView): '''投稿完了ページのビュー Attributes: template_name: レンダリングするテンプレート ''' # index.htmlをレンダリングする template_name ='post_success.html' class CategoryView(ListView): '''カテゴリページのビュー Attributes: template_name: レンダリングするテンプレート paginate_by: 1ページに表示するレコードの件数 ''' # index.htmlをレンダリングする template_name ='index.html' # 1ページに表示するレコードの件数 paginate_by = 9 def get_queryset(self): '''クエリを実行する self.kwargsの取得が必要なため、クラス変数querysetではなく、 get_queryset()のオーバーライドによりクエリを実行する Returns: クエリによって取得されたレコード ''' # self.kwargsでキーワードの辞書を取得し、 # categoryキーの値(Categorysテーブルのid)を取得 category_id = self.kwargs['category'] # filter(フィールド名=id)で絞り込む categories = PhotoPost.objects.filter( category=category_id).order_by('-posted_at') # クエリによって取得されたレコードを返す return categories class UserView(ListView): '''ユーザーの投稿一覧ページのビュー Attributes: template_name: レンダリングするテンプレート paginate_by: 1ページに表示するレコードの件数 ''' # index.htmlをレンダリングする template_name ='index.html' # 1ページに表示するレコードの件数 paginate_by = 9 def get_queryset(self): '''クエリを実行する self.kwargsの取得が必要なため、クラス変数querysetではなく、 get_queryset()のオーバーライドによりクエリを実行する Returns: クエリによって取得されたレコード ''' # self.kwargsでキーワードの辞書を取得し、 # userキーの値(ユーザーテーブルのid)を取得 user_id = self.kwargs['user'] # filter(フィールド名=id)で絞り込む user_list = PhotoPost.objects.filter( user=user_id).order_by('-posted_at') # クエリによって取得されたレコードを返す return user_list class DetailView(DetailView): '''詳細ページのビュー 投稿記事の詳細を表示するのでDetailViewを継承する Attributes: template_name: レンダリングするテンプレート model: モデルのクラス ''' # post.htmlをレンダリングする template_name ='detail.html' # クラス変数modelにモデルBlogPostを設定 model = PhotoPost class MypageView(ListView): '''マイページのビュー Attributes: template_name: レンダリングするテンプレート paginate_by: 1ページに表示するレコードの件数 ''' # mypage.htmlをレンダリングする template_name ='mypage.html' # 1ページに表示するレコードの件数 paginate_by = 9 def get_queryset(self): '''クエリを実行する self.kwargsの取得が必要なため、クラス変数querysetではなく、 get_queryset()のオーバーライドによりクエリを実行する Returns: クエリによって取得されたレコード ''' # 現在ログインしているユーザー名はHttpRequest.userに格納されている # filter(userフィールド=userオブジェクト)で絞り込む queryset = PhotoPost.objects.filter( user=self.request.user).order_by('-posted_at') # クエリによって取得されたレコードを返す return queryset class PhotoDeleteView(DeleteView): '''レコードの削除を行うビュー Attributes: model: モデル template_name: レンダリングするテンプレート paginate_by: 1ページに表示するレコードの件数 success_url: 削除完了後のリダイレクト先のURL ''' # 操作の対象はPhotoPostモデル model = PhotoPost # photo_delete.htmlをレンダリングする template_name ='photo_delete.html' # 処理完了後にマイページにリダイレクト success_url = reverse_lazy('photo:mypage') def delete(self, request, *args, **kwargs): '''レコードの削除を行う Parameters: self: PhotoDeleteViewオブジェクト request: WSGIRequest(HttpRequest)オブジェクト args: 引数として渡される辞書(dict) kwargs: キーワード付きの辞書(dict) {'pk': 21}のようにレコードのidが渡される Returns: HttpResponseRedirect(success_url)を返して success_urlにリダイレクト ''' # スーパークラスのdelete()を実行 return super().delete(request, *args, **kwargs) --------------------------------------------- ### 試したこと 書籍、ネットで検索フォームについて多々調べましたが、うまくできませんでした。 ### 補足情報(FW/ツールのバージョンなど)
あなたの回答
tips
プレビュー