آموزش پیداسازی جستجو در جنگو |  Django Search (with Q objects) Tutorial

به نام آن که جان را فکرت آموخت / چراغ دل به نور جان برافروختبا عرض سلام و وقت بخیر خدمت کاربران محترم سایت ویرگول، در این مقاله آموزشی که چکیده آموزش جنگو ORM از سایت Django documentation بهمراه مطالب تکمیلی تر , سعی شده یک آموزش کاربردی و پروژه محور از جنگو ORM ارایه گردد.ایده این سری مقاله های آموزشی از این موضوع سرچشمه می گیرد که بخشی از خوانندگان وجود دارد که به محتوای نوشتاری آنلاین بهتر پاسخ می دهند و ترجیج می دهند مهارت های جدید را به سرعت از طریق خواندن افزایش دهند.این سری آموزش ها با ارایه اولین پکیج آموزشی در خصوص جنگو آغاز می شود که انتظار می رود با واکنش مثبت کاربران همراه شود.توجه: این مقاله به مرور زمان، ویرایش و یا تکمیل می‌شود!تقاضا: در صورتی که با مشکل تایپی، دستوری و یا مفهومی در این مقاله برخورد کردید، از شما دوست عزیز و گرامی، صمیمانه تقاضا می‌کنم که اینجانب را مطلع کرده، تا نسبت به تصحیح و یا تکمیل آن، در اسرع وقت، اقدام نمایم. با کمال تشکر جواد جهانگیریشماره تلفن همراه: 09149431772نشانی پست الکترونیکی: javad.jahangiri.niopdc@gmail.comفیلم‌های آموزشی در آپارات:جواد جهانگیری (CTO) - آپاراتفیلم آموزشی در یوتویب: javad jahangiri - YouTubeنسخه مقاله: ۱.۱ - تاریخ بروزرسانی: 1401/01/07برای دیدن فیلم اموزشی مربوطه به کانال آپاراتی بنده به ادرس جواد جهانگیری (CTO) - آپارات مراجعه نماییدبرای این اموزش از منابع زیر استفاده شده استDjango | Documentation |Making queries |Complex lookups with Q objectsDjango | Documentation | Searchنکته:سورس های این پروژه در گیت هاب بنده در مسیر ذیل قابل دسترس می باشد:https://github.com/javadjahangiriniopdc/djangosearchحتما قبل از شروع به مطالعه این مقاله حتما مقاله قبلی بنده در راستا اموزش Django Orm از طریق لینک ذیل مطالعه فرمایید https://vrgl.ir/62xzv ابتدا یک پروژه جنگو ایجاد می کنیم پیشنهاد می شود برای کار با جنگو از IDE PyCharm استفاده نمایید و به شرح ذیل یک پروژه جنگو ایجاد می کنیموارد پنجره run manager.py task به شرح ذیل می شویمیک app جدید بنام myapp ایجاد می کنیمو app جدید به app های جنگو به شرح ذیل اضافه می کنیمدر app جدید اضافه شده در فایل models.py یک موجودیت بنام Person به شرح زیر ایجاد می کنیمدرنهایت یک مایگریشن ایجاد کرده و تغییرات بر روی دیتابیس مایگریت می کنیمیک سوپر کاربر ایجاد می نماییم:و موجودیت را به پنل admin اضافه می کنیموارد پنل admin جنگو شده و چندین رکورد برای جدول Person درج می کنیم:به اپ جدید myapp یک فایل urls.py به صورت زیر اضافه می کنیم :و در نهایت urls.py جدید اضافه شده در app اصلی جنگو به شکل زیر include می کنیمدر نهایت داخل فایل views.py شده و یک function view به شرح ذیل بنام home ایجاد می کنیمو یک فایل home.html به مسیر template اضافه می کنیم:دقت شود در جنگو برخی از اسامی دارای معنی خاصی هستند مانند static و templates اگر دقت شود در داخل فایل settings.py در قسمت تنظیمات static و templates تنظیماتی به شرح ذیل اعمال شده این به این معنی می باشد که جنگو در داخل هر app به دنبال پوشه های مذکور می گردد و برای سرویس از این پوشه ها استفاده می کنددر مورد پوشه templates اولویت ابتدا با templates که در مسیر root جنگو می باشد هست و سپس templates موجود در داخل هر app این به این معنی می باشد که اگر شما در داخل پوشه templates که در مسیر root جنگو یک فایل برای مثال index.html داشته باشید و در داخل پوشه templates که در مسیر هر app هم با این نام فایلی موجود باشد اولویت با index.html می باشد که در پوشه templates که در مسیر root جنگو هستنحوه تنظیم فایل static در جنگوبرای تنظیم فایل های static تنظیمات مقتضی توسط خود جنگو بصورت پیش فرض اعمال شده است و نیازی به اعمال تنظیم خاصی نیست ولی دقت شود در پایان برنامه نویسی پروژه در هنگام collectstatic نیاز به مسیر مربوط STATIC_ROOT دارد که به شکل زیر تنظیم می شود:STATIC_URL = 'static/' import os STATIC_ROOT = os.path.join(BASE_DIR, 'static')نکته:پیشنهاد می شود در داخل هر app دو پوشه بنام های static و templates ایجاد شود و در داخل هر پوشه یاد شده یک پوشه هم نام خود app ایجاد گردد دلیل این پیشنهاد این است که در نهایت که پوشه برای مد product اماده می شود در هنگام collectstatic تمامی فایل موجود در پوشه های static و templates هر app در یک پوشه static و templates در مسیر root جنگو تجمیع می گردد در این صورت اگر فایل هم نامی در app های ما باشد به مشکل جدی برخورد می کنیم ولی وقتی در داخل هر app در پوشه های static و templates یک پوشه بنام خود app ایجاد شود در هنگام تجمیع شدن در نهایت در یک پوشه واحد فایل هر app در داخل پوشه هم نام با خود app کپی می شود این مشکل تداخل نام دیگر وجود نخواهد داشت.همانطوری که در تصویر بالا مشاهده می کنید در داخل پوشه myapp یک پوشه بنام static ایجاد شده است و در داخل پوشه static هم یک پوشه بنام myapp همان با نام خود app ایجاد شده و همین کار برای پوشه templates هم تکرار شده است این کار مشکل تجمیع فایل در نهایت در پوشه های static و templates (فلش سوم) که در مسیر root پروژه جنگو در نهایت پس از پایان پروژه را مرتفع خواهد نمود.برای قالب پروژه پیشنهاد می شود از یکی از قالب های اموزشی موجود در سایت w3schools به شرح ذیل استفاده شودبر روی گزینه try your self کلیک نمایید و کد زیر برای شما نمایش داده می شود:<!DOCTYPE html> <html lang=&quoten&quot> <head> <title>Bootstrap 4 Website Example</title> <meta charset=&quotutf-8&quot> <meta name=&quotviewport&quot content=&quotwidth=device-width, initial-scale=1&quot> <link rel=&quotstylesheet&quot href=&quothttps://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css&quot> <script src=&quothttps://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.slim.min.js&quot> <script src=&quothttps://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js&quot> <script src=&quothttps://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js&quot> <style> .fakeimg { height: 200px; background: #aaa; } </style> </head> <body> <div class=&quotjumbotron text-center&quot style=&quotmargin-bottom:0&quot> <h1>My First Bootstrap 4 Page</h1> <p>Resize this responsive page to see the effect!</p> </div> <nav class=&quotnavbar navbar-expand-sm bg-dark navbar-dark&quot> <a class=&quotnavbar-brand&quot href=&quot#&quot>Navbar</a> <button class=&quotnavbar-toggler&quot type=&quotbutton&quot data-toggle=&quotcollapse&quot data-target=&quot#collapsibleNavbar&quot> <span class=&quotnavbar-toggler-icon&quot></span> </button> <div class=&quotcollapse navbar-collapse&quot id=&quotcollapsibleNavbar&quot> <ul class=&quotnavbar-nav&quot> <li class=&quotnav-item&quot> <a class=&quotnav-link&quot href=&quot#&quot>Link</a> </li> <li class=&quotnav-item&quot> <a class=&quotnav-link&quot href=&quot#&quot>Link</a> </li> <li class=&quotnav-item&quot> <a class=&quotnav-link&quot href=&quot#&quot>Link</a> </li> </ul> </div> </nav> <div class=&quotcontainer&quot style=&quotmargin-top:30px&quot> <div class=&quotrow&quot> <div class=&quotcol-sm-4&quot> <h2>About Me</h2> <h5>Photo of me:</h5> <div class=&quotfakeimg&quot>Fake Image</div> <p>Some text about me in culpa qui officia deserunt mollit anim..</p> <h3>Some Links</h3> <p>Lorem ipsum dolor sit ame.</p> <ul class=&quotnav nav-pills flex-column&quot> <li class=&quotnav-item&quot> <a class=&quotnav-link active&quot href=&quot#&quot>Active</a> </li> <li class=&quotnav-item&quot> <a class=&quotnav-link&quot href=&quot#&quot>Link</a> </li> <li class=&quotnav-item&quot> <a class=&quotnav-link&quot href=&quot#&quot>Link</a> </li> <li class=&quotnav-item&quot> <a class=&quotnav-link disabled&quot href=&quot#&quot>Disabled</a> </li> </ul> <hr class=&quotd-sm-none&quot> </div> <div class=&quotcol-sm-8&quot> <h2>TITLE HEADING</h2> <h5>Title description, Dec 7, 2017</h5> <div class=&quotfakeimg&quot>Fake Image</div> <p>Some text..</p> <p>Sunt in culpa qui officia deserunt mollit anim id est laborum consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco.</p> <br> <h2>TITLE HEADING</h2> <h5>Title description, Sep 2, 2017</h5> <div class=&quotfakeimg&quot>Fake Image</div> <p>Some text..</p> <p>Sunt in culpa qui officia deserunt mollit anim id est laborum consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco.</p> </div> </div> </div> <div class=&quotjumbotron text-center&quot style=&quotmargin-bottom:0&quot> <p>Footer</p> </div> </body> </html>در داخل پوشه myapp/templates/myapp یک فایل بنام base.html ایجاد می کنیم و از طریق کدهای بالا به شرح ذیل این فایل را تغییر می دهیمbase.html{% load static %} <!DOCTYPE html> <html lang=&quoten&quot> <head> <title>Bootstrap 4 Website Example</title> <meta charset=&quotutf-8&quot> <meta name=&quotviewport&quot content=&quotwidth=device-width, initial-scale=1&quot> <link rel=&quotstylesheet&quot href=&quot{% static 'myapp/css/bootstrap.min.css' %}&quot> <script src=&quot{% static 'myapp/js/jquery.slim.min.js' %}&quot> <script src=&quot{% static 'myapp/js/popper.min.js' %}&quot> <script src=&quot {% static 'myapp/js/bootstrap.bundle.min.js' %}&quot> <style> .fakeimg { height: 200px; background: #aaa; } </style> </head> <body> {% include 'myapp/header.html' %} <div class=&quotcontainer&quot style=&quotmargin-top:30px&quot> {% block content %} {% endblock %} </div> {% include 'myapp/footer.html' %} </body> </html>تنظیمات یک:بارگذاری فایل های استاتیک ابتدا فایل css و js مورد نیاز به شرح ذیل در پوشه myapp/static/myapp در داخل پوشه های cssوjs کپی می کنیمنحوه استفاده از فایل static در جنگوابتدا از طریق دستور زیر مسیردهی فایل های استاتیک را load می کنیم{% load static %}سپس از طریق زیر فایل های static را در فایل base.html لود می کنیم<script src=&quot{% static 'myapp/js/jquery.slim.min.js' %}&quot> <script src=&quot{% static 'myapp/js/popper.min.js' %}&quot> <script src=&quot {% static 'myapp/js/bootstrap.bundle.min.js' %}&quot>تنظیمات دوم:ایجاد فایل header.html و include ان در داخل فایل base.htmlheader.html<div class=&quotjumbotron text-center&quot style=&quotmargin-bottom:0&quot> <h1>My First Bootstrap 4 Page</h1> <p>Resize this responsive page to see the effect!</p> </div> {% include 'myapp/nav.html' %}کد مورد نیاز برای include کردن header.html در داخل فایل base.html{% include 'myapp/header.html' %}معمولا در پروژه های قسمت navigation ها (منوها) نیز به یک فایل جداگانه منتقل شده و در داخل header.html به شکل بالا include می شودnav.html<nav class=&quotnavbar navbar-expand-sm bg-dark navbar-dark&quot> <a class=&quotnavbar-brand&quot href=&quot#&quot>Navbar</a> <button class=&quotnavbar-toggler&quot type=&quotbutton&quot data-toggle=&quotcollapse&quot data-target=&quot#collapsibleNavbar&quot> <span class=&quotnavbar-toggler-icon&quot></span> </button> <div class=&quotcollapse navbar-collapse&quot id=&quotcollapsibleNavbar&quot> <ul class=&quotnavbar-nav&quot> <li class=&quotnav-item&quot> <a class=&quotnav-link&quot href=&quot#&quot>Link</a> </li> <li class=&quotnav-item&quot> <a class=&quotnav-link&quot href=&quot#&quot>Link</a> </li> <li class=&quotnav-item&quot> <a class=&quotnav-link&quot href=&quot#&quot>Link</a> </li> </ul> </div> </nav>تنظیمات سوم:نحوه block بندی فایل base.html و ایجاد ارث بری صفحه index.html از base.html<div class=&quotcontainer&quot style=&quotmargin-top:30px&quot> {% block content %} {% endblock %} </div>index.html{% extends 'myapp/base.html' %} {% load static %} {% block content %} <div class=&quotrow&quot> <div class=&quotcol-12&quot> <h1>index content</h1> </div> </div> {% endblock %}کد {% extends 'myapp/base.html' %} زیر برای ارث بری از صفحه base.html استفاده می شود در این صورت در هنگام بارگذاری صفحه index.html ابتدا صفحه base.html بارگذاری شده و سپس در داخل قسمت block content کدهای مربوط به صفحه index.html بارگذاری می شودتنظیمات قسمت چهارم:نحوه ایجاد فایل footer.html و include کردن فایل footer در base.htmlfooter.html<div class=&quotjumbotron text-center&quot style=&quotmargin-bottom:0&quot> <p>Footer</p> </div>اگر تنظیمات به درستی انجام شود در نهایت شما با خروجی به شکل ذیل روبه رو خواهید شدنحوه ارسال و نمایش اطلاعات Person در داخل فایل indexfrom django.shortcuts import render from myapp.models import Person def home(request): persons = Person.objects.all() return render(request, 'myapp/index.html', {'persons': persons})سپس کدهای مورد نیاز برای ایجاد جدول بوت استرپی را از لینک زیر استفاده کنیدhttps://getbootstrap.com/docs/4.0/content/tables/وکدهای جدول بوت استرپی به شرح ذیل به صفحه Index اضافه می کنیمindex.html{% extends 'myapp/base.html' %} {% load static %} {% block content %} <div class=&quotrow&quot> <div class=&quotcol-12&quot> <table class=&quottable&quot> <thead> <tr> <th scope=&quotcol&quot>name</th> <th scope=&quotcol&quot>description</th> </tr> </thead> <tbody> {% for person in persons %} <tr> <td>{{ person.name }}</td> <td>{{ person.description }}</td> </tr> {% endfor %} </tbody> </table> </div> </div> {% endblock %}و خروجی به شرح ذیل خواهد بودنحوه اضافه کردن forms به پروژه جنگویک فرم جنگو به پروژه به شرح ذیل اضافه می کنیمforms.pyfrom django import forms class SearchForm(forms.Form): search = forms.CharField() حالا تغییرات ذیل در فرم view.py به شرح ذیل اضافه می کنیم :درقسمت اول :فایل فرم که در مرحلی قبل ایجاد کردیم را در view واکشی می کنیم درقسمت دوم:بررسی می کنیم که اطلاعات ارسالی از سوی فرم که در مرحله بعدی به فایل index اضافه خواهد شد معتبر است یا نه ؟در مرحله سوم: با عنایت به اینکه می خواهیم از پرس و جو پیچیده استفاده کینم از object Q استفاده می کینم برای اطلاعات بیشتر می توانید از طریق لینک ذیل مطالب بیشتری را در این راستا مطالعه فرماییدhttps://docs.djangoproject.com/en/4.0/topics/db/queries/#complex-lookups-with-q-objectsهمچنین برای جستجو کردن به شرطی که شامل یک عبارت باشد و به حروف کوچیک و بزرگ هم حساس نباشد از icontains استفاده شده استدر مرحله چهارم:اطلاعات فرم به صفحه index بصورت دیکشنری ارسال می گردد.views.pyfrom datetime import datetime from django.db.models import Q from django.http import HttpResponse from django.shortcuts import render from myapp.forms import SearchForm from myapp.models import Person def home(request): persons = Person.objects.all() form = SearchForm() if 'search' in request.GET: form = SearchForm(request.GET) if form.is_valid(): cd = form.cleaned_data['search'] persons= persons.filter(Q(name__icontains=cd) | Q(description__icontains=cd)) return render(request, 'myapp/index.html', {'persons': persons, 'form': form})حالا در فایل index.html یک ردیف جدید بوت استرپی ایجاد کرده و به شرح ذیل فرم که در مرحله قبل به این صفحه پاس شده است را به صفحه html اضافه می کنیم:index.html{% extends 'myapp/base.html' %} {% load static %} {% block content %} <div class=&quotrow&quot> <div class=&quotcol-12&quot> <form action=&quot&quot> {{ form }} <input type=&quotsubmit&quot value=&quotSearch&quot> </form> </div> </div> <div class=&quotrow&quot style=&quotmargin-top: 50px&quot> <div class=&quotcol-12&quot> <table class=&quottable&quot> <thead> <tr> <th scope=&quotcol&quot>name</th> <th scope=&quotcol&quot>description</th> </tr> </thead> <tbody> {% for person in persons %} <tr> <td>{{ person.name }}</td> <td>{{ person.description }}</td> </tr> {% endfor %} </tbody> </table> </div> </div> {% endblock %}و در نهایت نتیجه خروجی برنامه به شرح ذیل خواهد بودباتشکر از مطالعه مقاله ,مثل همیشه کنجکاو باشید !!!در دوره های آموزش تضمینی مجتمع فنی ارومیه که به صورت خصوصی و عمومی در دو شیوه حضوری و آنلاین برگزار می شود سرفصل های بسیار متنوع و کاربردی را بصورت پروژه محور آموزش داده می شود تا شخص کارآموز بتواند بلافاصله پس از اتمام این دوره در کمترین زمان ممکن وارد بازار کار شود.آموزش تخصص ماست با ما حرفه ای شویدجهت مشاوره با شماره 09149431772 در ارتباط باشید ...