<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های جواد جهانگیری</title>
        <link>https://virgool.io/feed/@javadjahangiri</link>
        <description>بنده دارای مدارک بین المللی شبکه ,برنامه نویسی, سرورهای ویندوزی و لینوکس هستم  بیش از ده سال سابقه تدریس در زمینه های یاد شده  را دارم. آموزش تخصص ماست با ما حرفه ای شوید 09149431772 مجتمع فنی ارومیه</description>
        <language>fa</language>
        <pubDate>2026-06-17 05:23:06</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/1263553/avatar/U6XKPa.jpeg?height=120&amp;width=120</url>
            <title>جواد جهانگیری</title>
            <link>https://virgool.io/@javadjahangiri</link>
        </image>

                    <item>
                <title>آموزش  ملزومات لینوکس - linux essentials tutorial - linux LPIC</title>
                <link>https://virgool.io/@javadjahangiri/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%D9%85%D9%84%D8%B2%D9%88%D9%85%D8%A7%D8%AA-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-linux-essentials-tutorial-mzhpa7pahhvc</link>
                <description>زبه نام آن که جان را فکرت آموخت / چراغ دل به نور جان برافروختبا عرض سلام و وقت بخیر خدمت کاربران محترم سایت ویرگول، در این مقاله آموزشی که چکیده آموزش linux essentials از سایت Linux Professional Institute بهمراه مطالب تکمیلی تر , سعی شده یک آموزش کاربردی از دستورات کاربردی و مهم لینوکس ارایه گردد.ایده این سری مقاله های آموزشی از این موضوع سرچشمه می گیرد که بخشی از خوانندگان وجود دارد که به محتوای نوشتاری آنلاین بهتر پاسخ می دهند و ترجیج می دهند مهارت های جدید را به سرعت از طریق خواندن افزایش دهند.این سری آموزش ها با هدف ارایه اموزش سریع و کاربردی  آغاز شده که انتظار می رود با واکنش مثبت کاربران همراه شود.توجه: این مقاله به مرور زمان، ویرایش و یا تکمیل می‌شود!تقاضا: در صورتی که با مشکل تایپی، دستوری و یا مفهومی در این مقاله برخورد کردید، از شما دوست عزیز و گرامی، صمیمانه تقاضا می‌کنم که اینجانب را مطلع کرده، تا نسبت به تصحیح و یا تکمیل آن، در اسرع وقت، اقدام نمایم. با کمال تشکر جواد جهانگیریشماره تلفن همراه: 09149431772نشانی پست الکترونیکی: javad.jahangiri.niopdc@gmail.comفیلم‌های آموزشی در آپارات:جواد جهانگیری (CTO) - آپاراتفیلم آموزشی در یوتویب: javad jahangiri - YouTubeنسخه مقاله: ۱.۱ - تاریخ بروزرسانی: 1401/03/01برای دیدن فیلم اموزشی مربوطه به کانال آپاراتی بنده به ادرس جواد جهانگیری (CTO) - آپارات مراجعه نماییددر این اموزش در مورد دستورات اولیه و کاربردی  لینوکس کار می کنیم وهدف یادگیری لینوکس برای  اموزش های بعد امنیت اطلاعات و لینوکس کالی می باشد.در لینوکس  قدرت اصلی ان در ترمینال ان هستشآشنایی با لینوکس نیاز اصلی برنامه نویسان هستش که می خواهد بصورت حرفه ای کار کننداین سری از مقالات هدف آشنایی با مفاهیم هک  بوده و به مرور زمان با مفاهیم شبکه و مفاهیم برنامه نویسی و مفاهیم امنیت آشنا می شود و درنهایت هدف  اشنایی کلی با اصول هک ی ان برای امن سازی شبکه و برنامه ها و وب سایت ها می باشدسیستم عامل لینوکس مونولیتک بوده بخاطر یکپارچه بودن کرنل سرعت ان نسبت به ویندوز بیشتر هستش و در  سخت افزار مشابه تا 60 درصد سریعتر از ویندوز می باشد ان هستش پیشنهاد می شود برای تمرینات لینوکس را بصورت مجازی نصب کنیدویدیوهای اموزشی این مقاله در اپارات بنده در مسیر ذیل در دسترس می باشدhttps://www.aparat.com/playlist/332315هک با سرعت رو ترمینال زدن نیست ،مهم فکر کردن است و خلاقیت هستش و نوشتن اسکریبت ها کاربردی هستش و مهم برنامه نویسی و اشنا با اصول امنیت هستش ،درست هست سرعت تایپ مهم هستش ولی از ان مهتر فکر و خلاقت و مفاهیم هستشبیشتر سرور ها یا لینوکس هست و یا برای مجازی سازی از vmware  استفاده می کنند که نوعی لینوکس هستشCtrl+T باز کردن ترمینالCtrl+D بستن ترمینالهکر به معنای برنامه نویش لینوکس هستش چون برخی ها از برنامه نویس ها کارهای اشتباهی کردن معنای این کلمات بصورت امروزی هک برداشت می شودdate+4:30  شش ماهه دو سال+3:30  شش ماهه اول سالdate -u   تاریخ universal  یا جهانی رو میدهدر شش ماهه اول سال تاریخ و ساعت جهانی با +3:30 می شود و در شش ماهه دوم سال +4:30 می شودclear  پاک کردن صفحهecho javadecho “javad”برای چاپ کردن اطلاعات استفاده می شودhistory!53  دستور که در تاریخچه در ردیف 53 هستش اجرا شد!!  دستور اخر !1 دستور اول رو میارهhistory -c  تاریخچه رو پاک می کندمفهوم کرنل و مفهوم شلدستورات در شل وارد می کنیمانواع شل های لینوکسشل Bash Shell  معروف ترین و مهم ترین شل لینوکسی و پیش فرض اوبونتو هم شل هستش مثل زبان هستش و دستورات در حقیقت کلمات این زبان هستشcommand option input ساختار کلی دستورات در لینوکس هستشecho $PATHمحتویات داخل فایل PATH را نمایش می دهدوقتی ما دستوری می زنیم به ترتیب موجود در path را جستجو می کند اگر نتونست پیغام دستورات مشابه را نمایش می دهدwhich cal این دستور دارد از مسیر /usr/bin/cal اجرا می شودwhich echowhich whichcal تقویم رو نمایش می دهدcal 2018 تقویم تاریخ 2018 را نمایش می دهدcal 12  2018  ماه 12 سال 2018 را نمایش دهدcal -A 1 دقت کنید A با حرف بزرگ هستش یک ماه بعد Aftercal -B 1  دقت کنید B با حرف بزرگ هستش یک ماه قبل را نمایش می دهد Beforدستور helpبازدن دستور help به تنهایی دستوراتی که help ان موجود است نمایش داده می شودیک مثال از دستور helphelp cdدستور بعدی برای نمایش راهنما دستور man هستش برای مثالman whichبرای خروج از راهنمای man می توان از q استفاده کردن در دستور Man قسمت name کاری که دستور انجام می دهد را توضیح می دهد سیناپسیس شکل و سینتکس دستور را نمایس می دهد هر قسمتی که داخل [  ] باز و بسته باشد اختیاری هستش و اگر در اخر هر دستور ... دیدن یعنی می شود چندتا فایل باهم بزنیمwhich echo calدر لینوکس به سوئیچ دستورات options گفته می شود و به حروف بزرگ و کوچیک حساس می باشدls -l   با    ls -Hدر لینوکس اگر در اپشن دستورات به حالی   [    a  |  b   ] باشه یعنی اولا این دستورات اختیاری بود بعد می توان یا از a استفاده کرد یا bبرای مثال man dateاگر در اپشن دستورات بخواهیم از فرمت log name استفاده کنیم از دوتا دشت استفاده می کنیمdate -- utcدقت کنید دستور man دقیقا مثل به دفترچه راهنما می باشد اگر بخواهیم چیزی در ان جستجو کنیم از اپشن -k استفاده می کنیمman -k &amp;quotList directory content &amp;quotحالا دقت کنید این عبارت جستجو شده در صفحه اول دستور dir و صفحه اول ls و صفحه هشت دستور ntfsls و.. قابل نمایش می باشدبرای رفتن به صفحه اول از دستور راهنمای man به این شکل می باشدman dir 1Standard input / Standard output/ Standard Errorتوجه کنید input استاندارد کیبورد هستش و output استاندارد صفحه نمایش هستش و استاندارد Error پیش فرض هم Display هستشدر این مثال از ورودی استانداری می خونه و در خروجی استاندارد می نویسه&gt; برای ورودی دستوارت&lt; برای خروجی دستوراتcat &lt; مثالی از ورودی دستوراتcat &gt; مثالی از خروجی دستوراتبرای نمایش فایل های مخفی درمحیط گرافیکی لینوکس (ناتیلوس) به شکل زیر عمل می کنیمیک مثال از نحوه تغییر خروجی استانداردcat 1&gt;out.txt
amin
javad
rezaتوجه داشته باشید چون استاندارد خروجی پیش فرض یک هست لزومی به نوشتن ان یک نیست cat &gt;out.txtولی اگر می خواهیم استاندارد خروجی خطا را تغییر بدهیم حتما باید عدد 2 را بنویسیمcat -k  2&gt;error.txtچون ما اپشن -k را نداریم خطا می دهد و خطارو در فایل error.txt می نویسدنکته :&gt; یک برای create استفاده می کند ولی &gt;&gt; برای append  به فایل قبلی استفاده می شودcat  &gt;out.txt   cat  &gt;&gt;out.txtتوجه داشته باشید برای استاندارد ورودی پیش فرض همین حالت رو داریم &gt;0  و یا &gt; یکی هستشcat  &lt; 
cat  0&lt;می توانیم خروجی های و ورودی های استاندارد رو باهم ترکیب کینمcat  -k  1&gt;&gt;out.txt   2&gt;&gt;err.txt
cat -k &gt;&gt;out.txt 2&gt;&gt;err.txtیک فایل input.xt  ایجاد کنید و در ان مقدار اطلاعات وارد کنید بعد می توانیمcat &lt;input.txt
cat 0&lt;input.txtمی توانیم به این شکل این دستورات را با هم ترکیب کنیمcat  &lt;input.txt  &gt;out.txt</description>
                <category>جواد جهانگیری</category>
                <author>جواد جهانگیری</author>
                <pubDate>Sun, 19 Jun 2022 08:57:27 +0430</pubDate>
            </item>
                    <item>
                <title>آموزش عملیات CRUD در جنگو با Ajax</title>
                <link>https://virgool.io/@javadjahangiri/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%D8%B9%D9%85%D9%84%DB%8C%D8%A7%D8%AA-crud-%D8%AF%D8%B1-%D8%AC%D9%86%DA%AF%D9%88-%D8%A8%D8%A7-ajax-iexmpicdywat</link>
                <description>به نام آن که جان را فکرت آموخت / چراغ دل به نور جان برافروختبا عرض سلام و وقت بخیر خدمت کاربران محترم سایت ویرگول، در این مقاله آموزشی که چکیده آموزش جنگو از سایت Django documentation بهمراه مطالب تکمیلی تر , سعی شده یک آموزش کاربردی و پروژه محور از جنگو ارایه گردد.ایده این سری مقاله های آموزشی از این موضوع سرچشمه می گیرد که بخشی از خوانندگان وجود دارد که به محتوای نوشتاری آنلاین بهتر پاسخ می دهند و ترجیج می دهند مهارت های جدید را به سرعت از طریق خواندن افزایش دهند.این سری آموزش ها با ارایه اولین پکیج آموزشی در خصوص جنگو آغاز می شود که انتظار می رود با واکنش مثبت کاربران همراه شود.توجه: این مقاله به مرور زمان، ویرایش و یا تکمیل می‌شود!تقاضا: در صورتی که با مشکل تایپی، دستوری و یا مفهومی در این مقاله برخورد کردید، از شما دوست عزیز و گرامی، صمیمانه تقاضا می‌کنم که اینجانب را مطلع کرده، تا نسبت به تصحیح و یا تکمیل آن، در اسرع وقت، اقدام نمایم. با کمال تشکر جواد جهانگیریشماره تلفن همراه: 09149431772نشانی پست الکترونیکی: javad.jahangiri.niopdc@gmail.comفیلم‌های آموزشی در آپارات:جواد جهانگیری (CTO) - آپاراتفیلم آموزشی در یوتویب: javad jahangiri - YouTubeنسخه مقاله: ۱.۱ - تاریخ بروزرسانی: 1401/02/01برای دیدن فیلم اموزشی مربوطه به کانال آپاراتی بنده به ادرس جواد جهانگیری (CTO) - آپارات مراجعه نماییدسورس این پروژه بر روی github بنده در ادرس زیر موجود می باشدhttps://github.com/javadjahangiriniopdc/SimpleDjangoCrudAjaxBasic Configurationدر این آموزش قصد داریم از JQuery برای پیاده سازی درخواست های Ajax استفاده کنیم. JQuery ساده و آسان برای یادگیری است.base.html{% load static %}
&lt;!doctype html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;meta charset=&amp;quotutf-8&amp;quot&gt;
    &lt;title&gt;{% block title %}Title{% endblock title %}&lt;/title&gt;
    &lt;link rel=&amp;quotstylesheet&amp;quot href=&amp;quothttps://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css&amp;quot integrity=&amp;quotsha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u&amp;quot crossorigin=&amp;quotanonymous&amp;quot&gt;
    {% block stylesheet %}{% endblock stylesheet %}
  &lt;/head&gt;
  &lt;body&gt;
    &lt;main&gt;
    {% block content %}
    {% endblock content %}
    &lt;/main&gt;
    &lt;script src=&amp;quothttps://code.jquery.com/jquery-3.1.0.min.js&amp;quot&gt;
    &lt;script &gt;
    {% block javascript %}
    {% endblock javascript%}
  &lt;/body&gt;
&lt;/html&gt;من همچنین از Bootstrap برای یک رابط کاربری زیبا استفاده می کنم. برای JQuery و Bootstrap، ما از CDN استفاده می کنیم.Example – Django Ajax CRUD Operationsاکنون زمان آن است که با Ajax Calls همراه شوید.Create and Read User Django Ajaxما از هیچ forms.py استفاده نخواهیم کرد، ما فرم HTML را مستقیماً در قالب داریم. همانطور که در فایل crud.html ما مشاهده می کنید.اگر می خواهید جنگو فرم شما را بسازد، می توانید از فرم های crispy forms استفاده کنید.بیایید یک نمای برای رسیدگی به درخواست Ajax ایجاد کنیم.# Views.py

from .models import CrudUser
from django.views.generic import View
from django.http import JsonResponse

class CreateCrudUser(View):
    def  get(self, request):
        name1 = request.GET.get(&#039;name&#039;, None)
        address1 = request.GET.get(&#039;address&#039;, None)
        age1 = request.GET.get(&#039;age&#039;, None)

        obj = CrudUser.objects.create(
            name = name1,
            address = address1,
            age = age1
        )

        user = {&#039;id&#039;:obj.id,&#039;name&#039;:obj.name,&#039;address&#039;:obj.address,&#039;age&#039;:obj.age}

        data = {
            &#039;user&#039;: user
        }
        return JsonResponse(data)توجه - ما قالب را رندر نمی کنیم، فقط JsonResponse را برمی گردانیم و همچنین از روش Ajax Get استفاده می کنیم.ما داده‌های فرم را با استفاده از request.GET.get دریافت می‌کنیم (آدرس، هیچ)، آدرس ویژگی نام ورودی فرم است. سپس یک کاربر ایجاد می کنیم و کاربری را که ایجاد کرده ایم برای نمایش در صفحه وب برمی گردانیم.# urls.py
from django.urls import path
from crud_ajax import views 

urlpatterns = [
    path(&#039;crud/&#039;,  views.CrudView.as_view(), name=&#039;crud_ajax&#039;),
    path(&#039;ajax/crud/create/&#039;,  views.CreateCrudUser.as_view(), name=&#039;crud_ajax_create&#039;),
]Form in Crud.html for adding Users.&lt;form id=&amp;quotaddUser&amp;quot action=&amp;quot&amp;quot&gt;
          &lt;div class=&amp;quotform-group&amp;quot&gt;
            &lt;input class=&amp;quotform-control&amp;quot type=&amp;quottext&amp;quot name=&amp;quotname&amp;quot placeholder=&amp;quotName&amp;quot required&gt;
          &lt;/div&gt;
          &lt;div class=&amp;quotform-group&amp;quot&gt;
            &lt;input class=&amp;quotform-control&amp;quot type=&amp;quottext&amp;quot name=&amp;quotaddress&amp;quot placeholder=&amp;quotAddress&amp;quot required&gt;
          &lt;/div&gt;
          &lt;div class=&amp;quotform-group&amp;quot&gt;
            &lt;input class=&amp;quotform-control&amp;quot type=&amp;quotnumber&amp;quot name=&amp;quotage&amp;quot min=&amp;quot10&amp;quot max=&amp;quot100&amp;quot placeholder=&amp;quotAge&amp;quot required&gt;
          &lt;/div&gt;
          &lt;button class=&amp;quotbtn btn-primary form-control&amp;quot type=&amp;quotsubmit&amp;quot&gt;SUBMIT&lt;/button&gt;
&lt;/form&gt;اکنون اجازه دهید دوباره درخواست javascript و jquery ajax را در Crud.html که در هنگام لیست کردن کاربران ایجاد کرده ایم اضافه کنیم.Crud.html...

{% block javascript %}

// Create Django Ajax Call
$(&amp;quotform#addUser&amp;quot).submit(function() {
    var nameInput = $(&#039;input[name=&amp;quotname&amp;quot]&#039;).val().trim();
    var addressInput = $(&#039;input[name=&amp;quotaddress&amp;quot]&#039;).val().trim();
    var ageInput = $(&#039;input[name=&amp;quotage&amp;quot]&#039;).val().trim();
    if (nameInput &amp;&amp; addressInput &amp;&amp; ageInput) {
        // Create Ajax Call
        $.ajax({
            url: &#039;{% url &amp;quotcrud_ajax_create&amp;quot %}&#039;,
            data: {
                &#039;name&#039;: nameInput,
                &#039;address&#039;: addressInput,
                &#039;age&#039;: ageInput
            },
            dataType: &#039;json&#039;,
            success: function (data) {
                if (data.user) {
                  appendToUsrTable(data.user);
                }
            }
        });
      } else {
        alert&#40;&amp;quotAll fields must have a valid value.&amp;quot&#41;;
    }
    $(&#039;form#addUser&#039;).trigger(&amp;quotreset&amp;quot);
    return false;
});
function appendToUsrTable(user) {
  $(&amp;quot#userTable &gt; tbody:last-child&amp;quot).append(`
        &lt;tr id=&amp;quotuser-${user.id}&amp;quot&gt;
            &lt;td class=&amp;quotuserName&amp;quot name=&amp;quotname&amp;quot&gt;${user.name}&lt;/td&gt;
            &#039;&lt;td class=&amp;quotuserAddress&amp;quot name=&amp;quotaddress&amp;quot&gt;${user.address}&lt;/td&gt;
            &#039;&lt;td class=&amp;quotuserAge&amp;quot name=&amp;quotage&amp;quot&gt;${user.age}&lt;/td&gt;
            &#039;&lt;td align=&amp;quotcenter&amp;quot&gt;
                &lt;button class=&amp;quotbtn btn-success form-control&amp;quot =&amp;quoteditUser(${user.id})&amp;quot data-toggle=&amp;quotmodal&amp;quot data-target=&amp;quot#myModal&amp;quot)&amp;quot&gt;EDIT&lt;/button&gt;
            &lt;/td&gt;
            &lt;td align=&amp;quotcenter&amp;quot&gt;
                &lt;button class=&amp;quotbtn btn-danger form-control&amp;quot =&amp;quotdeleteUser(${user.id})&amp;quot&gt;DELETE&lt;/button&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
    `);
}

{% endblock javascript %}عملکرد JQuery فوق به این صورت است که وقتی فرم id=&#x27;addUser&#x27; را ارسال می کنید، مقادیر فیلدهای ورودی را می گیرد و فراخوانی ajax به سرور منتقل می شود.$.ajax({
            url: &#039;{% url &amp;quotcrud_ajax_create&amp;quot %}&#039;,
            data: {
                &#039;name&#039;: nameInput,
                &#039;address&#039;: addressInput,
                &#039;age&#039;: ageInput
            },
            dataType: &#039;json&#039;,
            success: function (data) {
                if (data.user) {
                  appendToUsrTable(data.user);
                }
            }
});اجازه دهید بفهمیم که درخواست ajax بالا به مرورگر چه دستوری می دهد.URL – where resource is located:url: &#x27;/ajax/crud/create/&#x27;,Data Type – Type of Data we want in return:dataType: &#039;json&#039;,Return Data – Dictionary of data what we want to send:data: {
                &#039;name&#039;: nameInput,
                &#039;address&#039;: addressInput,
                &#039;age&#039;: ageInput
      }Success Response – Once we receive response from ajax, execute the code:success: function (data) {
                if (data.user) {
                  appendToUsrTable(data.user);
                }
            }زمانی که کاربر فرم را پر کرده و ارسال می کند. داده های ارسالی به سرور می رود و پس از تایید به پایگاه داده و تابع appendToUsrTable فراخوانی می شود. این تابع appendToUsrTable فقط یک jQuery است که در آن کاربری را که با استفاده از User Add Form اضافه کرده ایم اضافه می کند. هنگامی که یک کاربر اضافه می شود به شکل زیر خواهد بود:Update User Django Ajax# Views.py

class UpdateCrudUser(View):
    def  get(self, request):
        id1 = request.GET.get(&#039;id&#039;, None)
        name1 = request.GET.get(&#039;name&#039;, None)
        address1 = request.GET.get(&#039;address&#039;, None)
        age1 = request.GET.get(&#039;age&#039;, None)

        obj = CrudUser.objects.get(id=id1)
        obj.name = name1
        obj.address = address1
        obj.age = age1
        obj.save()

        user = {&#039;id&#039;:obj.id,&#039;name&#039;:obj.name,&#039;address&#039;:obj.address,&#039;age&#039;:obj.age}

        data = {
            &#039;user&#039;: user
        }
        return JsonResponse(data)# urls.py

from django.urls import path
from crud_ajaximport  views  

urlpatterns = [
    path(&#039;crud/&#039;,  views.CrudView.as_view(), name=&#039;crud_ajax&#039;),
    path(&#039;ajax/crud/create/&#039;,  views.CreateCrudUser.as_view(), name=&#039;crud_ajax_create&#039;),
    path(&#039;ajax/crud/update/&#039;,  views.UpdateCrudUser.as_view(), name=&#039;crud_ajax_update&#039;),
]crud.html...
// Create Django Ajax Call
$(&amp;quotform#updateUser&amp;quot).submit(function() {
    var idInput = $(&#039;input[name=&amp;quotformId&amp;quot]&#039;).val().trim();
    var nameInput = $(&#039;input[name=&amp;quotformName&amp;quot]&#039;).val().trim();
    var addressInput = $(&#039;input[name=&amp;quotformAddress&amp;quot]&#039;).val().trim();
    var ageInput = $(&#039;input[name=&amp;quotformAge&amp;quot]&#039;).val().trim();
    if (nameInput &amp;&amp; addressInput &amp;&amp; ageInput) {
        // Create Ajax Call
        $.ajax({
            url: &#039;{% url &amp;quotcrud_ajax_update&amp;quot %}&#039;,
            data: {
                &#039;id&#039;: idInput,
                &#039;name&#039;: nameInput,
                &#039;address&#039;: addressInput,
                &#039;age&#039;: ageInput
            },
            dataType: &#039;json&#039;,
            success: function (data) {
                if (data.user) {
                  updateToUserTabel(data.user);
                }
            }
        });
       } else {
        alert&#40;&amp;quotAll fields must have a valid value.&amp;quot&#41;;
    }
    $(&#039;form#updateUser&#039;).trigger(&amp;quotreset&amp;quot);
    $(&#039;#myModal&#039;).modal(&#039;hide&#039;);
    return false;
});

// Update Django Ajax Call
function editUser(id) {
  if (id) {
    tr_id = &amp;quot#user-&amp;quot + id;
    name = $(tr_id).find(&amp;quot.userName&amp;quot).text();
    address = $(tr_id).find(&amp;quot.userAddress&amp;quot).text();
    age = $(tr_id).find(&amp;quot.userAge&amp;quot).text();
    $(&#039;#form-id&#039;).val(id);
    $(&#039;#form-name&#039;).val(name);
    $(&#039;#form-address&#039;).val(address);
    $(&#039;#form-age&#039;).val(age);
  }
}
function updateToUserTabel(user){
    $(&amp;quot#userTable #user-&amp;quot + user.id).children(&amp;quot.userData&amp;quot).each(function() {
        var attr = $(this).attr(&amp;quotname&amp;quot);
        if (attr == &amp;quotname&amp;quot) {
          $(this).text(user.name);
        } else if (attr == &amp;quotaddress&amp;quot) {
          $(this).text(user.address);
        } else {
          $(this).text(user.age);
        }
      });
}به‌روزرسانی کاربر مشابه Create User است. در views.py به جای ایجاد پرس و جو، از کوئری به روز رسانی استفاده می کنیم.در فراخوانی Ajax Request، یک پارامتر id دیگر برای شناسایی ردیف در پایگاه داده ارسال می کنیمما همچنین از دو تابع jQuery استفاده می کنیم - editUser و updateToUserTabelدر editUser – برای به روز رسانی فرم id=”updateUser” که داخل modal است استفاده می شود. و updateToUserTabel در موفقیت درخواست Ajax برای به‌روزرسانی جزئیات کاربری که به‌روزرسانی کرده‌ایم استفاده می‌شود.Delete User Django Ajax# Views.py

class DeleteCrudUser(View):
    def  get(self, request):
        id1 = request.GET.get(&#039;id&#039;, None)
        CrudUser.objects.get(id=id1).delete()
        data = {
            &#039;deleted&#039;: True
        }
        return JsonResponse(data)# urls.py

from django.urls import path
from crud_ajax import views 

urlpatterns = [
    path(&#039;crud/&#039;,  views.CrudView.as_view(), name=&#039;crud_ajax&#039;),
    path(&#039;ajax/crud/create/&#039;,  views.CreateCrudUser.as_view(), name=&#039;crud_ajax_create&#039;),
    path(&#039;ajax/crud/update/&#039;,  views.UpdateCrudUser.as_view(), name=&#039;crud_ajax_update&#039;),
    path(&#039;ajax/crud/delete/&#039;,  views.DeleteCrudUser.as_view(), name=&#039;crud_ajax_delete&#039;),
]Crud.html// Delete Django Ajax Call
function deleteUser(id) {
  var action = confirm&#40;&amp;quotAre you sure you want to delete this user?&amp;quot&#41;;
  if (action != false) {
    $.ajax({
        url: &#039;{% url &amp;quotcrud_ajax_delete&amp;quot %}&#039;,
        data: {
            &#039;id&#039;: id,
        },
        dataType: &#039;json&#039;,
        success: function (data) {
            if (data.deleted) {
              $(&amp;quot#userTable #user-&amp;quot + id).remove();
            }
        }
    });
  }
}حذف کاربر با استفاده از Ajax Django یکی از ساده ترین راه ها است. در درخواست ajax، ما یک شناسه از شی را ارسال می کنیم که می خواهیم آن را حذف کنیم تا مشاهده شود. در View، query حذف اجرا می شود و پرچم حذف شده در Response ارسال می شود. در موفقیت، ما مستقیماً تابع jQuery را می نویسیم تا بخشی را که می خواهیم با استفاده از id به صورت پویا از جدول حذف کنیم، حذف می کنیم.توجه: این مقاله به مرور زمان، ویرایش و یا تکمیل می‌شود!تقاضا: در صورتی که با مشکل تایپی، دستوری و یا مفهومی در این مقاله برخورد کردید، از شما دوست عزیز و گرامی، صمیمانه تقاضا می‌کنم که اینجانب را مطلع کرده، تا نسبت به تصحیح و یا تکمیل آن، در اسرع وقت، اقدام نمایم. با کمال تشکر جواد جهانگیریشماره تلفن همراه: 09149431772نشانی پست الکترونیکی: javad.jahangiri.niopdc@gmail.comفیلم‌های آموزشی در آپارات:جواد جهانگیری (CTO) - آپاراتفیلم آموزشی در یوتویب: javad jahangiri - YouTubeنسخه مقاله: ۱.۱ - تاریخ بروزرسانی: 1401/01/07برای دیدن فیلم اموزشی مربوطه به کانال آپاراتی بنده به ادرس جواد جهانگیری (CTO) - آپارات مراجعه نماییدباتشکر از مطالعه مقاله ,مثل همیشه کنجکاو باشید !!!در دوره های آموزش تضمینی مجتمع فنی ارومیه که به صورت خصوصی و عمومی در دو شیوه حضوری و آنلاین برگزار می شود سرفصل های بسیار متنوع و کاربردی را بصورت پروژه محور آموزش داده می شود تا شخص کارآموز بتواند بلافاصله پس از اتمام این دوره در کمترین زمان ممکن وارد بازار کار شود.آموزش تخصص ماست با ما حرفه ای شویدجهت مشاوره با شماره 09149431772 در ارتباط باشید ...</description>
                <category>جواد جهانگیری</category>
                <author>جواد جهانگیری</author>
                <pubDate>Sun, 24 Apr 2022 12:46:22 +0430</pubDate>
            </item>
                    <item>
                <title>Django CRUD (Create Read Update Delete) Example</title>
                <link>https://virgool.io/@javadjahangiri/django-crud-create-read-update-delete-example-o8prwfy6atzk</link>
                <description>ه نام آن که جان را فکرت آموخت / چراغ دل به نور جان برافروختبا عرض سلام و وقت بخیر خدمت کاربران محترم سایت ویرگول، در این مقاله آموزشی که چکیده آموزش جنگو ORM از سایت Django documentation بهمراه مطالب تکمیلی تر , سعی شده یک آموزش کاربردی و پروژه محور از جنگو ORM ارایه گردد.ایده این سری مقاله های آموزشی از این موضوع سرچشمه می گیرد که بخشی از خوانندگان وجود دارد که به محتوای نوشتاری آنلاین بهتر پاسخ می دهند و ترجیج می دهند مهارت های جدید را به سرعت از طریق خواندن افزایش دهند.این سری آموزش ها با ارایه اولین پکیج آموزشی در خصوص جنگو آغاز می شود که انتظار می رود با واکنش مثبت کاربران همراه شود.توجه: این مقاله به مرور زمان، ویرایش و یا تکمیل می‌شود!تقاضا: در صورتی که با مشکل تایپی، دستوری و یا مفهومی در این مقاله برخورد کردید، از شما دوست عزیز و گرامی، صمیمانه تقاضا می‌کنم که اینجانب را مطلع کرده، تا نسبت به تصحیح و یا تکمیل آن، در اسرع وقت، اقدام نمایم. با کمال تشکر جواد جهانگیریشماره تلفن همراه: 09149431772نشانی پست الکترونیکی: javad.jahangiri.niopdc@gmail.comفیلم‌های آموزشی در آپارات:جواد جهانگیری (CTO) - آپاراتفیلم آموزشی در یوتویب: javad jahangiri - YouTubeنسخه مقاله: ۱.۱ - تاریخ بروزرسانی: 1401/02/01برای دیدن فیلم اموزشی مربوطه به کانال آپاراتی بنده به ادرس جواد جهانگیری (CTO) - آپارات مراجعه نماییدسورس این پروژه در گیت هاب بنده به ادرس زیر موجود می باشدhttps://github.com/javadjahangiriniopdc/DjangoCrudExampleیک پروژه Django ایجاد می کنیمیک app جدید بنام employee ایجاد می کنیمدر فایل settingنسبت به اضافه کردن app جدید اقدام می کنیمبا عنایت به اینکه می خواهیم در این پروژه از دیتابیس MySQL استفاده کنیم ابتدا نسبت به نصب VisualCppRedist_AIO_x86_x64 از سایت soft98 اقدام می کنیمMicrosoft Visual C++ Runtimeبرخی نرم افزارها که با استفاده از کتابخانه ها و Component های زبان ++Visual C نوشته شده اند، به طور عادی بر روی سیستم اجرا نمیشوند و با ارورهایی مانند MSVCP120.dll و MSVCP140.dll و VCRUNTIME و... مواجه میشوید و برای اجرا نیازمند تعدادی فایل هستند که باید بر روی سیستم موجود باشد. Microsoft Visual C++ Runtime در حقیقت تعدادی فایل مورد نیاز سیستم عامل است تا بتواند برنامه های نوشته شده تحت این زبان ها را اجرا کندسپس نسبت به نسب WampServer بر روی ویندوز از سایت soft98 اقدام می کنیم نصب ان ساده بود فقط دقت شود که با عنایت به اینکه برای کار نیاز به Microsoft Visual C++ Runtime دارد حتما قبل از نصب مطابق اموزش اقدام شود.WampServerیکی از بهترین و قدیمی ترین نرم افزارهای لوکال ساز محسوب میشود این نرم افزار یک نرم افزار برای راه اندازی IIS‌ لینوکس هست که شما بوسیله آن میتوانید فایل های پی اچ پی را اجرا و نتیجه آن را ببینید . شما میتوانید توسط این نرم افزار همه اسکریپت های PHP را بر روی لوکال تست نمایید.برخی ویژگی های WampServerقابلیت سوئیچ بین  تمامی نسخه های Php  MySQL  Apacheامکان مدیریت تمام سرویس های نصب شدهامکان دسترسی به تمام ماژول های php و قابلیت فعال یا غیر فعال سازی هر یک از آنها تنها با یک کلیکامکان دسترسی به تنظیمات هر کدام از سرویس هاقابلیت اسفاده از بانک اطلاعاتی  sqlitemanagerقابلیت استفاده از phpmyadmin برای مدیریت بانک های اطلاعاتیو ....نصب WampServer  ساده بود و به گزینه پیش فرض پسند کرده و نصب را تا اخرین مرحله ادامه دهید درصورتی که عملیات صحیح باشد بعد از اجرای WampServer  می بایستی ایکون ان در کنار ساعت ویندوز به رنگ سبز باشد اگر به رنگ نارنجی باشد به این معنی هست که یکی از سرویس ها بدرستی اجرا نشده است با عنایت به اینکه اکثر دانت کور کار ها معمولا بر روی سیستم خود IIS را فعال می کند پورت 80 برای این سرور تخصیص داده می شود و هنگام که سرویس Appache می خواهد راه اندازی شود این پورت use است لذا بر روی ایکون  WampServer مطابق شکل راست کلیک کرده و  نسبت به تغییر پورت اقدام می کنیممعمولا پورت را به 8080 تغییر می دهیمدرنهایت اگر عملیات به درستی انجام شود ایکون WampServer به شکل سبز خواهد بود با عنایت به اینکه در این اموزش هدف اموزش MySQL نیست و در صورت نیاز به اموزش MySQL  از اپارات بنده از دوره اموش کاردی و پروژه محور MySQL  استفاده نماییدلیست پخش اموزش کاربردی MySQLیک دیتابیس جدید بنام djangodb با Collation از نوع utf8_general_ci اقدام می کنیم :سپس مجدد به پروژه Django  خود برگشته و فایل تنظیمات دیتابیس پیش فرض را به شکل زیر تغییر می دهیمDATABASES = {
    &#039;default&#039;: {
        &#039;ENGINE&#039;: &#039;django.db.backends.mysql&#039;,
        &#039;NAME&#039;: &#039;djangodb&#039;,
        &#039;USER&#039;: &#039;root&#039;,
        &#039;PASSWORD&#039;: &#039;mysql&#039;,
        &#039;HOST&#039;: &#039;localhost&#039;,
        &#039;PORT&#039;: &#039;3306&#039;
    }
}پیشنهاد می شود برای درک بهتر این اموزش ابتدا از دوره های رایگان بنده در اپارت به شرح زیر استفاده شود https://www.aparat.com/playlist/802207 دوره MySQL در پایتوندوره آموزش جنگومطابق اموزش های ارایه شده می بایستی در این مرحله نسبت به نسبت mysqlclient اقدام شودایجاد مدل Employeeوارد فایل models.py در APP جدید ایجاد شده می شود و یک مدل بنام Employee را ایجاد می کنیم:from django.db import models


class Employee(models.Model):
    eid = models.CharField(max_length=20)
    ename = models.CharField(max_length=100)
    eemail = models.EmailField()
    econtact = models.CharField(max_length=15)

    class Meta:
        db_table = &amp;quotemployee&amp;quotنسبت به makemigration و در ادامه migrate پروژه اقدام می کنیمیک کاربر superuser نیز برای ورود به پنل ادمین ایجاد می کنیمدر ادامه نسبت به رجیستر کردن مدل کارمند در admin Panel جنگو به شکل زیر اقدام می کنیمfrom django.contrib import admin

# Register your models here.
from employee.models import Employee

admin.site.register(Employee)وارد پنل admin شده و چندین رکورد برای مدل Employee اقدام می کنیمیک فایل یک فرم بنام forms.py به پروژه اضافه می کنیمfroms.pyfrom django import forms
from employee.models import Employee


class EmployeeForm(forms.ModelForm):
    class Meta:
        model = Employee
        fields = &amp;quot__all__&amp;quotدر داخل پوشه employee یک فایل بنام employee/urls.py ایجاد می کنیم و سپس به شرح ذیل ان را در داخل urls.py ایجاد می کنیم:urls.pyfrom django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path(&#039;admin/&#039;, admin.site.urls),
    path(&#039;&#039;, include(&#039;employee.urls&#039;))
]در داخل app کارمند ایجاد شده پوشه های templates و static را به شرح ذیل ایجاد می کنیم:یک فایل index.html در مسیر employee/templates/employee/index.html ایجاد می کنیم##employee/templates/employee/index.html&lt;!DOCTYPE html&gt;
{% load static %}
&lt;html lang=&amp;quoten&amp;quot&gt;
&lt;head&gt;
    &lt;meta charset=&amp;quotUTF-8&amp;quot&gt;
    &lt;title&gt;Index&lt;/title&gt;
    &lt;link rel=&amp;quotstylesheet&amp;quot href=&amp;quothttps://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css&amp;quot
          integrity=&amp;quotsha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn&amp;quot crossorigin=&amp;quotanonymous&amp;quot&gt;
    &lt;script src=&amp;quothttps://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js&amp;quot
            integrity=&amp;quotsha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj&amp;quot
            crossorigin=&amp;quotanonymous&amp;quot&gt;
    &lt;script src=&amp;quothttps://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js&amp;quot
            integrity=&amp;quotsha384-fQybjgWLrvvRgtW6bFlB7jaZrFsaBXjsOMm/tB9LTS58ONXgqbR9W8oWht/amnpF&amp;quot
            crossorigin=&amp;quotanonymous&amp;quot&gt;
    &lt;link rel=&amp;quotstylesheet&amp;quot href=&amp;quot{% static &#039;employee/css/style.css&#039; %}&amp;quot/&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;form method=&amp;quotPOST&amp;quot class=&amp;quotpost-form&amp;quot action=&amp;quot/emp&amp;quot&gt;
        {% csrf_token %}
    &lt;div class=&amp;quotcontainer&amp;quot&gt;
&lt;br&gt;
    &lt;div class=&amp;quotform-group row&amp;quot&gt;
    &lt;label class=&amp;quotcol-sm-1 col-form-label&amp;quot&gt;&lt;/label&gt;
    &lt;div class=&amp;quotcol-sm-4&amp;quot&gt;
    &lt;h3&gt;Enter Details&lt;/h3&gt;
    &lt;/div&gt;
  &lt;/div&gt;
    &lt;div class=&amp;quotform-group row&amp;quot&gt;
    &lt;label class=&amp;quotcol-sm-2 col-form-label&amp;quot&gt;Employee Id:&lt;/label&gt;
    &lt;div class=&amp;quotcol-sm-4&amp;quot&gt;
      {{ form.eid }}
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&amp;quotform-group row&amp;quot&gt;
    &lt;label class=&amp;quotcol-sm-2 col-form-label&amp;quot&gt;Employee Name:&lt;/label&gt;
    &lt;div class=&amp;quotcol-sm-4&amp;quot&gt;
      {{ form.ename }}
    &lt;/div&gt;
  &lt;/div&gt;
    &lt;div class=&amp;quotform-group row&amp;quot&gt;
    &lt;label class=&amp;quotcol-sm-2 col-form-label&amp;quot&gt;Employee Email:&lt;/label&gt;
    &lt;div class=&amp;quotcol-sm-4&amp;quot&gt;
      {{ form.eemail }}
    &lt;/div&gt;
  &lt;/div&gt;
    &lt;div class=&amp;quotform-group row&amp;quot&gt;
    &lt;label class=&amp;quotcol-sm-2 col-form-label&amp;quot&gt;Employee Contact:&lt;/label&gt;
    &lt;div class=&amp;quotcol-sm-4&amp;quot&gt;
      {{ form.econtact }}
    &lt;/div&gt;
  &lt;/div&gt;
    &lt;div class=&amp;quotform-group row&amp;quot&gt;
    &lt;label class=&amp;quotcol-sm-1 col-form-label&amp;quot&gt;&lt;/label&gt;
    &lt;div class=&amp;quotcol-sm-4&amp;quot&gt;
    &lt;button type=&amp;quotsubmit&amp;quot class=&amp;quotbtn btn-primary&amp;quot&gt;Submit&lt;/button&gt;
    &lt;/div&gt;
  &lt;/div&gt;
    &lt;/div&gt;
&lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;یک فایل show.html نیز در  مسیر employee/templates/employee/show.html ایجاد می کنیم##employee/templates/employee/show.html&lt;!DOCTYPE html&gt;
{% load static %}
&lt;html lang=&amp;quoten&amp;quot&gt;
&lt;head&gt;
    &lt;meta charset=&amp;quotUTF-8&amp;quot&gt;
    &lt;title&gt;Employee Records&lt;/title&gt;
    &lt;link rel=&amp;quotstylesheet&amp;quot href=&amp;quothttps://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css&amp;quot
          integrity=&amp;quotsha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn&amp;quot crossorigin=&amp;quotanonymous&amp;quot&gt;
    &lt;script src=&amp;quothttps://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js&amp;quot
            integrity=&amp;quotsha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj&amp;quot
            crossorigin=&amp;quotanonymous&amp;quot&gt;
    &lt;script src=&amp;quothttps://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js&amp;quot
            integrity=&amp;quotsha384-fQybjgWLrvvRgtW6bFlB7jaZrFsaBXjsOMm/tB9LTS58ONXgqbR9W8oWht/amnpF&amp;quot
            crossorigin=&amp;quotanonymous&amp;quot&gt;
    &lt;link rel=&amp;quotstylesheet&amp;quot href=&amp;quot{% static &#039;employee/css/style.css&#039; %}&amp;quot/&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;table class=&amp;quottable table-striped table-bordered table-sm&amp;quot&gt;
    &lt;thead class=&amp;quotthead-dark&amp;quot&gt;
    &lt;tr&gt;
        &lt;th&gt;Employee ID&lt;/th&gt;
        &lt;th&gt;Employee Name&lt;/th&gt;
        &lt;th&gt;Employee Email&lt;/th&gt;
        &lt;th&gt;Employee Contact&lt;/th&gt;
        &lt;th&gt;Actions&lt;/th&gt;
    &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
    {% for employee in employees %}
        &lt;tr&gt;
            &lt;td&gt;{{ employee.eid }}&lt;/td&gt;
            &lt;td&gt;{{ employee.ename }}&lt;/td&gt;
            &lt;td&gt;{{ employee.eemail }}&lt;/td&gt;
            &lt;td&gt;{{ employee.econtact }}&lt;/td&gt;
            &lt;td&gt;
                &lt;a href=&amp;quot/edit/{{ employee.id }}&amp;quot&gt;&lt;span class=&amp;quotglyphicon glyphicon-pencil&amp;quot&gt;Edit&lt;/span&gt;&lt;/a&gt;
                &lt;a href=&amp;quot/delete/{{ employee.id }}&amp;quot&gt;Delete&lt;/a&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
    {% endfor %}
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
&lt;br&gt;
&lt;center&gt;&lt;a href=&amp;quot/emp&amp;quot class=&amp;quotbtn btn-primary&amp;quot&gt;Add New Record&lt;/a&gt;&lt;/center&gt;
&lt;/body&gt;
&lt;/html&gt;یک فایل show.html نیز در  مسیر employee/templates/employee/edit.html ایجاد می کنیم ##employee/templates/employee/edit.html{% load static %}
&lt;!DOCTYPE html&gt;
&lt;html lang=&amp;quoten&amp;quot&gt;
&lt;head&gt;
    &lt;meta charset=&amp;quotUTF-8&amp;quot&gt;
    &lt;title&gt;Index&lt;/title&gt;
       &lt;link rel=&amp;quotstylesheet&amp;quot href=&amp;quothttps://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css&amp;quot
          integrity=&amp;quotsha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn&amp;quot crossorigin=&amp;quotanonymous&amp;quot&gt;
    &lt;script src=&amp;quothttps://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js&amp;quot
            integrity=&amp;quotsha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj&amp;quot
            crossorigin=&amp;quotanonymous&amp;quot&gt;
    &lt;script src=&amp;quothttps://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js&amp;quot
            integrity=&amp;quotsha384-fQybjgWLrvvRgtW6bFlB7jaZrFsaBXjsOMm/tB9LTS58ONXgqbR9W8oWht/amnpF&amp;quot
            crossorigin=&amp;quotanonymous&amp;quot&gt;
    &lt;link rel=&amp;quotstylesheet&amp;quot href=&amp;quot{% static &#039;employee/css/style.css&#039; %}&amp;quot/&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;form method=&amp;quotPOST&amp;quot class=&amp;quotpost-form&amp;quot action=&amp;quot/update/{{ employee.id }}&amp;quot&gt;
    {% csrf_token %}
    &lt;div class=&amp;quotcontainer&amp;quot&gt;
        &lt;br&gt;
        &lt;div class=&amp;quotform-group row&amp;quot&gt;
            &lt;label class=&amp;quotcol-sm-1 col-form-label&amp;quot&gt;&lt;/label&gt;
            &lt;div class=&amp;quotcol-sm-4&amp;quot&gt;
                &lt;h3&gt;Update Details&lt;/h3&gt;
            &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class=&amp;quotform-group row&amp;quot&gt;
            &lt;label class=&amp;quotcol-sm-2 col-form-label&amp;quot&gt;Employee Id:&lt;/label&gt;
            &lt;div class=&amp;quotcol-sm-4&amp;quot&gt;
                &lt;input type=&amp;quottext&amp;quot name=&amp;quoteid&amp;quot id=&amp;quotid_eid&amp;quot required maxlength=&amp;quot20&amp;quot value=&amp;quot{{ employee.eid }}&amp;quot/&gt;
            &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class=&amp;quotform-group row&amp;quot&gt;
            &lt;label class=&amp;quotcol-sm-2 col-form-label&amp;quot&gt;Employee Name:&lt;/label&gt;
            &lt;div class=&amp;quotcol-sm-4&amp;quot&gt;
                &lt;input type=&amp;quottext&amp;quot name=&amp;quotename&amp;quot id=&amp;quotid_ename&amp;quot required maxlength=&amp;quot100&amp;quot value=&amp;quot{{ employee.ename }}&amp;quot/&gt;
            &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class=&amp;quotform-group row&amp;quot&gt;
            &lt;label class=&amp;quotcol-sm-2 col-form-label&amp;quot&gt;Employee Email:&lt;/label&gt;
            &lt;div class=&amp;quotcol-sm-4&amp;quot&gt;
                &lt;input type=&amp;quotemail&amp;quot name=&amp;quoteemail&amp;quot id=&amp;quotid_eemail&amp;quot required maxlength=&amp;quot254&amp;quot
                       value=&amp;quot{{ employee.eemail }}&amp;quot/&gt;
            &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class=&amp;quotform-group row&amp;quot&gt;
            &lt;label class=&amp;quotcol-sm-2 col-form-label&amp;quot&gt;Employee Contact:&lt;/label&gt;
            &lt;div class=&amp;quotcol-sm-4&amp;quot&gt;
                &lt;input type=&amp;quottext&amp;quot name=&amp;quotecontact&amp;quot id=&amp;quotid_econtact&amp;quot required maxlength=&amp;quot15&amp;quot
                       value=&amp;quot{{ employee.econtact }}&amp;quot/&gt;
            &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class=&amp;quotform-group row&amp;quot&gt;
            &lt;label class=&amp;quotcol-sm-1 col-form-label&amp;quot&gt;&lt;/label&gt;
            &lt;div class=&amp;quotcol-sm-4&amp;quot&gt;
                &lt;button type=&amp;quotsubmit&amp;quot class=&amp;quotbtn btn-success&amp;quot&gt;Update&lt;/button&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;در داخل پوشه employee/static/employee یک پوشه بنام css ایجاد کرده و یک فایل style.css در این پوشه ایجاد می کنیم##employee/static/employee/css/style.cssbody {
    font: 12px/1.4 Verdana, Arial;
    background: #eee;
    height: 100%;
    margin: 25px 0;
    padding: 0
}

h1 {
    font: 24px Georgia, Verdana;
    margin: 0
}

h2 {
    font-size: 12px;
    font-weight: 400;
    font-style: italic;
    margin: 0 0 20px
}

p {
    margin-top: 0
}

ul {
    margin: 0;
    padding-left: 20px
}

#testdiv {
    width: 600px;
    margin: 0 auto;
    border: 1px solid #ccc;
    padding: 20px 25px;
    background: #fff
}

#tinybox {
    position: absolute;
    display: none;
    padding: 10px;
    background: #fff url(images/preload.gif) no-repeat 50% 50%;
    border: 10px solid #e3e3e3;
    z-index: 2000
}

#tinymask {
    position: absolute;
    display: none;
    top: 0;
    left: 0;
    height: 100%;
    width: 100%;
    background: #000;
    z-index: 1500
}

#tinycontent {
    background: #fff
}

.button {
    font: 14px Georgia, Verdana;
    margin-bottom: 10px;
    padding: 8px 10px 9px;
    border: 1px solid #ccc;
    background: #eee;
    cursor: pointer
}

.button:hover {
    border: 1px solid #bbb;
    background: #e3e3e3
}دقت شود بوت استرپ در فایل index.html به شکل زیر در بالا بارگذاری شده استدر فایل employee/urls.py نسبت به تعریف روتینگ به شرح ذیل اقدام می کنیم ##employee/urls.pyfrom django.contrib import admin
from django.urls import path, include

from employee import views

urlpatterns = [
    path(&#039;&#039;, views.show),
    path(&#039;emp&#039;, views.emp),
    path(&#039;show&#039;, views.show),
    path(&#039;edit/&lt;int:id&gt;&#039;, views.edit),
    path(&#039;update/&lt;int:id&gt;&#039;, views.update),
    path(&#039;delete/&lt;int:id&gt;&#039;, views.destroy),
]سپس فایل employee/views.py به شرح ذیل تعریف می کنیم##employee/views.pyfrom django.shortcuts import render

# Create your views here.
from django.shortcuts import render, redirect
from employee.forms import EmployeeForm
from employee.models import Employee


# Create your views here.
def emp(request):
    if request.method == &amp;quotPOST&amp;quot:
        form = EmployeeForm(request.POST)
        if form.is_valid():
            try:
                form.save()
                return redirect(&#039;/show&#039;)
            except:
                pass
    else:
        form = EmployeeForm()
    return render(request, &#039;employee/index.html&#039;, {&#039;form&#039;: form})


def show(request):
    employees = Employee.objects.all()
    return render(request, &amp;quotemployee/show.html&amp;quot, {&#039;employees&#039;: employees})


def edit(request, id):
    employee = Employee.objects.get(id=id)
    return render(request, &#039;employee/edit.html&#039;, {&#039;employee&#039;: employee})


def update(request, id):
    employee = Employee.objects.get(id=id)
    form = EmployeeForm(request.POST, instance=employee)
    if form.is_valid():
        form.save()
        return redirect(&amp;quot/show&amp;quot)
    return render(request, &#039;employee/edit.html&#039;, {&#039;employee&#039;: employee})


def destroy(request, id):
    employee = Employee.objects.get(id=id)
    employee.delete()
    return redirect(&amp;quot/show&amp;quot)نمونه از صفحه نمایش اطلاعاتنمونه از صفحه درج اطلاعاتنمونه از صفحه ویرایش اطلاعاتحذف اطلاعاتباتشکر از مطالعه مقاله ,مثل همیشه کنجکاو باشید !!!در دوره های آموزش تضمینی مجتمع فنی ارومیه که به صورت خصوصی و عمومی در دو شیوه حضوری و آنلاین برگزار می شود سرفصل های بسیار متنوع و کاربردی را بصورت پروژه محور آموزش داده می شود تا شخص کارآموز بتواند بلافاصله پس از اتمام این دوره در کمترین زمان ممکن وارد بازار کار شود.آموزش تخصص ماست با ما حرفه ای شویدجهت مشاوره با شماره 09149431772 در ارتباط باشید ...</description>
                <category>جواد جهانگیری</category>
                <author>جواد جهانگیری</author>
                <pubDate>Sat, 09 Apr 2022 15:23:01 +0430</pubDate>
            </item>
                    <item>
                <title>آموزش پیداسازی جستجو در جنگو |  Django Search (with Q objects) Tutorial</title>
                <link>https://virgool.io/@javadjahangiri/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%D9%BE%DB%8C%D8%AF%D8%A7%D8%B3%D8%A7%D8%B2%DB%8C-%D8%AC%D8%B3%D8%AA%D8%AC%D9%88-%D8%AF%D8%B1-%D8%AC%D9%86%DA%AF%D9%88-%D8%A8%D8%A7-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-%D8%A7%D8%A8%D8%AC%DA%A9%D8%AA-q-django-search-with-q-objects-tutorial-mvw7uzbbdxb9</link>
                <description>به نام آن که جان را فکرت آموخت / چراغ دل به نور جان برافروختبا عرض سلام و وقت بخیر خدمت کاربران محترم سایت ویرگول، در این مقاله آموزشی که چکیده آموزش جنگو 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 = &#039;static/&#039;
import os
STATIC_ROOT = os.path.join(BASE_DIR, &#039;static&#039;)نکته:پیشنهاد می شود در داخل هر 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 کلیک نمایید و کد زیر برای شما نمایش داده می شود:&lt;!DOCTYPE html&gt;
&lt;html lang=&amp;quoten&amp;quot&gt;
&lt;head&gt;
  &lt;title&gt;Bootstrap 4 Website Example&lt;/title&gt;
  &lt;meta charset=&amp;quotutf-8&amp;quot&gt;
  &lt;meta name=&amp;quotviewport&amp;quot content=&amp;quotwidth=device-width, initial-scale=1&amp;quot&gt;
  &lt;link rel=&amp;quotstylesheet&amp;quot href=&amp;quothttps://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css&amp;quot&gt;
  &lt;script src=&amp;quothttps://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.slim.min.js&amp;quot&gt;
  &lt;script src=&amp;quothttps://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js&amp;quot&gt;
  &lt;script src=&amp;quothttps://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js&amp;quot&gt;
  &lt;style&gt;
  .fakeimg {
    height: 200px;
    background: #aaa;
  }
  &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class=&amp;quotjumbotron text-center&amp;quot style=&amp;quotmargin-bottom:0&amp;quot&gt;
  &lt;h1&gt;My First Bootstrap 4 Page&lt;/h1&gt;
  &lt;p&gt;Resize this responsive page to see the effect!&lt;/p&gt;
&lt;/div&gt;

&lt;nav class=&amp;quotnavbar navbar-expand-sm bg-dark navbar-dark&amp;quot&gt;
  &lt;a class=&amp;quotnavbar-brand&amp;quot href=&amp;quot#&amp;quot&gt;Navbar&lt;/a&gt;
  &lt;button class=&amp;quotnavbar-toggler&amp;quot type=&amp;quotbutton&amp;quot data-toggle=&amp;quotcollapse&amp;quot data-target=&amp;quot#collapsibleNavbar&amp;quot&gt;
    &lt;span class=&amp;quotnavbar-toggler-icon&amp;quot&gt;&lt;/span&gt;
  &lt;/button&gt;
  &lt;div class=&amp;quotcollapse navbar-collapse&amp;quot id=&amp;quotcollapsibleNavbar&amp;quot&gt;
    &lt;ul class=&amp;quotnavbar-nav&amp;quot&gt;
      &lt;li class=&amp;quotnav-item&amp;quot&gt;
        &lt;a class=&amp;quotnav-link&amp;quot href=&amp;quot#&amp;quot&gt;Link&lt;/a&gt;
      &lt;/li&gt;
      &lt;li class=&amp;quotnav-item&amp;quot&gt;
        &lt;a class=&amp;quotnav-link&amp;quot href=&amp;quot#&amp;quot&gt;Link&lt;/a&gt;
      &lt;/li&gt;
      &lt;li class=&amp;quotnav-item&amp;quot&gt;
        &lt;a class=&amp;quotnav-link&amp;quot href=&amp;quot#&amp;quot&gt;Link&lt;/a&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/nav&gt;

&lt;div class=&amp;quotcontainer&amp;quot style=&amp;quotmargin-top:30px&amp;quot&gt;
  &lt;div class=&amp;quotrow&amp;quot&gt;
    &lt;div class=&amp;quotcol-sm-4&amp;quot&gt;
      &lt;h2&gt;About Me&lt;/h2&gt;
      &lt;h5&gt;Photo of me:&lt;/h5&gt;
      &lt;div class=&amp;quotfakeimg&amp;quot&gt;Fake Image&lt;/div&gt;
      &lt;p&gt;Some text about me in culpa qui officia deserunt mollit anim..&lt;/p&gt;
      &lt;h3&gt;Some Links&lt;/h3&gt;
      &lt;p&gt;Lorem ipsum dolor sit ame.&lt;/p&gt;
      &lt;ul class=&amp;quotnav nav-pills flex-column&amp;quot&gt;
        &lt;li class=&amp;quotnav-item&amp;quot&gt;
          &lt;a class=&amp;quotnav-link active&amp;quot href=&amp;quot#&amp;quot&gt;Active&lt;/a&gt;
        &lt;/li&gt;
        &lt;li class=&amp;quotnav-item&amp;quot&gt;
          &lt;a class=&amp;quotnav-link&amp;quot href=&amp;quot#&amp;quot&gt;Link&lt;/a&gt;
        &lt;/li&gt;
        &lt;li class=&amp;quotnav-item&amp;quot&gt;
          &lt;a class=&amp;quotnav-link&amp;quot href=&amp;quot#&amp;quot&gt;Link&lt;/a&gt;
        &lt;/li&gt;
        &lt;li class=&amp;quotnav-item&amp;quot&gt;
          &lt;a class=&amp;quotnav-link disabled&amp;quot href=&amp;quot#&amp;quot&gt;Disabled&lt;/a&gt;
        &lt;/li&gt;
      &lt;/ul&gt;
      &lt;hr class=&amp;quotd-sm-none&amp;quot&gt;
    &lt;/div&gt;
    &lt;div class=&amp;quotcol-sm-8&amp;quot&gt;
      &lt;h2&gt;TITLE HEADING&lt;/h2&gt;
      &lt;h5&gt;Title description, Dec 7, 2017&lt;/h5&gt;
      &lt;div class=&amp;quotfakeimg&amp;quot&gt;Fake Image&lt;/div&gt;
      &lt;p&gt;Some text..&lt;/p&gt;
      &lt;p&gt;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.&lt;/p&gt;
      &lt;br&gt;
      &lt;h2&gt;TITLE HEADING&lt;/h2&gt;
      &lt;h5&gt;Title description, Sep 2, 2017&lt;/h5&gt;
      &lt;div class=&amp;quotfakeimg&amp;quot&gt;Fake Image&lt;/div&gt;
      &lt;p&gt;Some text..&lt;/p&gt;
      &lt;p&gt;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.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;div class=&amp;quotjumbotron text-center&amp;quot style=&amp;quotmargin-bottom:0&amp;quot&gt;
  &lt;p&gt;Footer&lt;/p&gt;
&lt;/div&gt;

&lt;/body&gt;
&lt;/html&gt;در داخل پوشه myapp/templates/myapp یک فایل بنام base.html ایجاد می کنیم و از طریق کدهای بالا به شرح ذیل این فایل را تغییر می دهیمbase.html{% load static %}

&lt;!DOCTYPE html&gt;
&lt;html lang=&amp;quoten&amp;quot&gt;
&lt;head&gt;
    &lt;title&gt;Bootstrap 4 Website Example&lt;/title&gt;
    &lt;meta charset=&amp;quotutf-8&amp;quot&gt;
    &lt;meta name=&amp;quotviewport&amp;quot content=&amp;quotwidth=device-width, initial-scale=1&amp;quot&gt;
    &lt;link rel=&amp;quotstylesheet&amp;quot href=&amp;quot{% static &#039;myapp/css/bootstrap.min.css&#039; %}&amp;quot&gt;
    &lt;script src=&amp;quot{% static &#039;myapp/js/jquery.slim.min.js&#039; %}&amp;quot&gt;
    &lt;script src=&amp;quot{% static &#039;myapp/js/popper.min.js&#039; %}&amp;quot&gt;
    &lt;script src=&amp;quot {% static &#039;myapp/js/bootstrap.bundle.min.js&#039; %}&amp;quot&gt;
    &lt;style&gt;
        .fakeimg {
            height: 200px;
            background: #aaa;
        }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;


{% include &#039;myapp/header.html&#039; %}

&lt;div class=&amp;quotcontainer&amp;quot style=&amp;quotmargin-top:30px&amp;quot&gt;
    {% block content %}
    {% endblock %}
&lt;/div&gt;

{% include &#039;myapp/footer.html&#039; %}

&lt;/body&gt;
&lt;/html&gt;تنظیمات یک:بارگذاری فایل های استاتیک ابتدا فایل css و js مورد نیاز به شرح ذیل در پوشه myapp/static/myapp در داخل پوشه های cssوjs کپی می کنیمنحوه استفاده از فایل static در جنگوابتدا از طریق دستور زیر مسیردهی فایل های استاتیک را load می کنیم{% load static %}سپس از طریق زیر فایل های static را در فایل base.html لود می کنیم&lt;script src=&amp;quot{% static &#039;myapp/js/jquery.slim.min.js&#039; %}&amp;quot&gt;
&lt;script src=&amp;quot{% static &#039;myapp/js/popper.min.js&#039; %}&amp;quot&gt;
&lt;script src=&amp;quot {% static &#039;myapp/js/bootstrap.bundle.min.js&#039; %}&amp;quot&gt;تنظیمات دوم:ایجاد فایل header.html و include ان در داخل فایل base.htmlheader.html&lt;div class=&amp;quotjumbotron text-center&amp;quot style=&amp;quotmargin-bottom:0&amp;quot&gt;
  &lt;h1&gt;My First Bootstrap 4 Page&lt;/h1&gt;
  &lt;p&gt;Resize this responsive page to see the effect!&lt;/p&gt;
&lt;/div&gt;

{% include &#039;myapp/nav.html&#039; %}کد مورد نیاز برای include کردن header.html در داخل فایل base.html{% include &#039;myapp/header.html&#039; %}معمولا در پروژه های قسمت navigation ها (منوها) نیز به یک فایل جداگانه منتقل شده و در داخل header.html به شکل بالا include می شودnav.html&lt;nav class=&amp;quotnavbar navbar-expand-sm bg-dark navbar-dark&amp;quot&gt;
  &lt;a class=&amp;quotnavbar-brand&amp;quot href=&amp;quot#&amp;quot&gt;Navbar&lt;/a&gt;
  &lt;button class=&amp;quotnavbar-toggler&amp;quot type=&amp;quotbutton&amp;quot data-toggle=&amp;quotcollapse&amp;quot data-target=&amp;quot#collapsibleNavbar&amp;quot&gt;
    &lt;span class=&amp;quotnavbar-toggler-icon&amp;quot&gt;&lt;/span&gt;
  &lt;/button&gt;
  &lt;div class=&amp;quotcollapse navbar-collapse&amp;quot id=&amp;quotcollapsibleNavbar&amp;quot&gt;
    &lt;ul class=&amp;quotnavbar-nav&amp;quot&gt;
      &lt;li class=&amp;quotnav-item&amp;quot&gt;
        &lt;a class=&amp;quotnav-link&amp;quot href=&amp;quot#&amp;quot&gt;Link&lt;/a&gt;
      &lt;/li&gt;
      &lt;li class=&amp;quotnav-item&amp;quot&gt;
        &lt;a class=&amp;quotnav-link&amp;quot href=&amp;quot#&amp;quot&gt;Link&lt;/a&gt;
      &lt;/li&gt;
      &lt;li class=&amp;quotnav-item&amp;quot&gt;
        &lt;a class=&amp;quotnav-link&amp;quot href=&amp;quot#&amp;quot&gt;Link&lt;/a&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/nav&gt;تنظیمات سوم:نحوه block بندی فایل base.html و ایجاد ارث بری صفحه index.html از base.html&lt;div class=&amp;quotcontainer&amp;quot style=&amp;quotmargin-top:30px&amp;quot&gt;
    {% block content %}
    {% endblock %}
&lt;/div&gt;index.html{% extends &#039;myapp/base.html&#039; %}
{% load static %}
{% block content %}

    &lt;div class=&amp;quotrow&amp;quot&gt;
        &lt;div class=&amp;quotcol-12&amp;quot&gt;
                &lt;h1&gt;index content&lt;/h1&gt;
        &lt;/div&gt;
    &lt;/div&gt;

{% endblock %}کد {% extends &#x27;myapp/base.html&#x27; %} زیر برای ارث بری از صفحه base.html استفاده می شود در این صورت در هنگام بارگذاری صفحه index.html ابتدا صفحه base.html بارگذاری شده و سپس در داخل قسمت block content کدهای مربوط به صفحه index.html بارگذاری می شودتنظیمات قسمت چهارم:نحوه ایجاد فایل footer.html و include کردن فایل footer در base.htmlfooter.html&lt;div class=&amp;quotjumbotron text-center&amp;quot style=&amp;quotmargin-bottom:0&amp;quot&gt;
  &lt;p&gt;Footer&lt;/p&gt;
&lt;/div&gt;اگر تنظیمات به درستی انجام شود در نهایت شما با خروجی به شکل ذیل روبه رو خواهید شدنحوه ارسال و نمایش اطلاعات Person در داخل فایل indexfrom django.shortcuts import render
from myapp.models import Person


def home(request):
    persons = Person.objects.all()
    return render(request, &#039;myapp/index.html&#039;, {&#039;persons&#039;: persons})سپس کدهای مورد نیاز برای ایجاد جدول بوت استرپی را از لینک زیر استفاده کنیدhttps://getbootstrap.com/docs/4.0/content/tables/وکدهای جدول بوت استرپی به شرح ذیل به صفحه Index اضافه می کنیمindex.html{% extends &#039;myapp/base.html&#039; %}
{% load static %}
{% block content %}

    &lt;div class=&amp;quotrow&amp;quot&gt;
        &lt;div class=&amp;quotcol-12&amp;quot&gt;
            &lt;table class=&amp;quottable&amp;quot&gt;
                &lt;thead&gt;
                &lt;tr&gt;
                    &lt;th scope=&amp;quotcol&amp;quot&gt;name&lt;/th&gt;
                    &lt;th scope=&amp;quotcol&amp;quot&gt;description&lt;/th&gt;
                &lt;/tr&gt;
                &lt;/thead&gt;
                &lt;tbody&gt;
                {% for person in persons %}
                    &lt;tr&gt;
                        &lt;td&gt;{{ person.name }}&lt;/td&gt;
                        &lt;td&gt;{{ person.description }}&lt;/td&gt;
                    &lt;/tr&gt;
                {% endfor %}
                &lt;/tbody&gt;
            &lt;/table&gt;
        &lt;/div&gt;
    &lt;/div&gt;

{% 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 &#039;search&#039; in request.GET:
        form = SearchForm(request.GET)
        if form.is_valid():
            cd = form.cleaned_data[&#039;search&#039;]
            persons= persons.filter(Q(name__icontains=cd) | Q(description__icontains=cd))

    return render(request, &#039;myapp/index.html&#039;, {&#039;persons&#039;: persons, &#039;form&#039;: form})حالا در فایل index.html یک ردیف جدید بوت استرپی ایجاد کرده و به شرح ذیل فرم که در مرحله قبل به این صفحه پاس شده است را به صفحه html اضافه می کنیم:index.html{% extends &#039;myapp/base.html&#039; %}
{% load static %}
{% block content %}

    &lt;div class=&amp;quotrow&amp;quot&gt;
        &lt;div class=&amp;quotcol-12&amp;quot&gt;
            &lt;form action=&amp;quot&amp;quot&gt;
                {{ form }}
                &lt;input type=&amp;quotsubmit&amp;quot value=&amp;quotSearch&amp;quot&gt;
            &lt;/form&gt;

        &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class=&amp;quotrow&amp;quot style=&amp;quotmargin-top: 50px&amp;quot&gt;
        &lt;div class=&amp;quotcol-12&amp;quot&gt;
            &lt;table class=&amp;quottable&amp;quot&gt;
                &lt;thead&gt;
                &lt;tr&gt;
                    &lt;th scope=&amp;quotcol&amp;quot&gt;name&lt;/th&gt;
                    &lt;th scope=&amp;quotcol&amp;quot&gt;description&lt;/th&gt;
                &lt;/tr&gt;
                &lt;/thead&gt;
                &lt;tbody&gt;
                {% for person in persons %}
                    &lt;tr&gt;
                        &lt;td&gt;{{ person.name }}&lt;/td&gt;
                        &lt;td&gt;{{ person.description }}&lt;/td&gt;
                    &lt;/tr&gt;
                {% endfor %}
                &lt;/tbody&gt;
            &lt;/table&gt;
        &lt;/div&gt;
    &lt;/div&gt;

{% endblock %}و در نهایت نتیجه خروجی برنامه به شرح ذیل خواهد بودباتشکر از مطالعه مقاله ,مثل همیشه کنجکاو باشید !!!در دوره های آموزش تضمینی مجتمع فنی ارومیه که به صورت خصوصی و عمومی در دو شیوه حضوری و آنلاین برگزار می شود سرفصل های بسیار متنوع و کاربردی را بصورت پروژه محور آموزش داده می شود تا شخص کارآموز بتواند بلافاصله پس از اتمام این دوره در کمترین زمان ممکن وارد بازار کار شود.آموزش تخصص ماست با ما حرفه ای شویدجهت مشاوره با شماره 09149431772 در ارتباط باشید ...</description>
                <category>جواد جهانگیری</category>
                <author>جواد جهانگیری</author>
                <pubDate>Mon, 28 Mar 2022 12:36:44 +0430</pubDate>
            </item>
                    <item>
                <title>آموزش نحوه کار با Django ORM | Django ORM | جنگو ORM</title>
                <link>https://virgool.io/@javadjahangiri/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%D9%86%D8%AD%D9%88%D9%87-%DA%A9%D8%A7%D8%B1-%D8%A8%D8%A7-django-orm-django-orm-%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%D8%AC%D9%86%DA%AF%D9%88-orm-ujk8h1aavsxo</link>
                <description>به نام آن که جان را فکرت آموخت / چراغ دل به نور جان برافروختبا عرض سلام و وقت بخیر خدمت کاربران محترم سایت ویرگول، در این مقاله آموزشی که چکیده آموزش جنگو ORM از سایت Django documentation  بهمراه مطالب تکمیلی تر , سعی شده یک آموزش کاربردی و پروژه محور از جنگو ORM ارایه گردد.ایده این سری مقاله های آموزشی از این موضوع سرچشمه می گیرد که بخشی از خوانندگان وجود دارد که به محتوای نوشتاری آنلاین بهتر پاسخ می دهند و ترجیج می دهند مهارت های جدید را به سرعت از طریق خواندن افزایش دهند.این سری آموزش ها با ارایه اولین پکیج آموزشی در خصوص جنگو آغاز می شود که انتظار می رود با واکنش مثبت کاربران همراه شود.Django ORMتوجه: این مقاله به مرور زمان، ویرایش و یا تکمیل می‌شود!تقاضا: در صورتی که با مشکل تایپی، دستوری و یا مفهومی در این مقاله برخورد کردید، از شما دوست عزیز و گرامی، صمیمانه تقاضا می‌کنم که اینجانب را مطلع کرده، تا نسبت به تصحیح و یا تکمیل آن، در اسرع وقت، اقدام نمایم. با کمال تشکر جواد جهانگیریشماره تلفن همراه: 09149431772نشانی پست الکترونیکی: javad.jahangiri.niopdc@gmail.comفیلم‌های آموزشی در آپارات:جواد جهانگیری (CTO) - آپاراتفیلم آموزشی در یوتویب: javad jahangiri - YouTubeنسخه مقاله: ۱.۱ - تاریخ بروزرسانی: 1401/01/01برای دیدن فیلم اموزشی مربوطه به کانال آپاراتی بنده به ادرس جواد جهانگیری (CTO) - آپارات مراجعه نماییددقت شود برای دانلود سورس پروژه می توانید به گیت هاب بنده به ادرس زیر مراجعه نماییدhttps://github.com/javadjahangiriniopdc/djangoormtutorialsدر این آموزش، بحث کاملی در مورد کوئری های ORM جنگو و نحوه استفاده از آنها برای دستکاری داده ها خواهیم داشت.Django ORM یکی از بهترین ابزارهای جنگو است و نقش بسیار اساسی در انجام وظایف مربوط به پایگاه داده ایفا می کند.Django ORM از انتزاع سهولت استفاده تشکیل شده است. &quot;چیزهای ساده آسان و چیزهای سخت را ممکن می کند.در اینجا توضیح مفصلی در مورد هر پرس و جوی ORM خواهیم داشت و همچنین پرس و جوهای SQL مرتبط با آنها را مشاهده می کنیم.ابتدا یک پروژه جنگو ایجاد می کنیم پیشنهاد می شود برای فعالیت حرفه ای با جنگو از IDE حرفه ای PyCharm شرکت JetBrains که برای کار حرفه با  پایتون و فریم های ورک های پایتونی ایجاد شده است استفاده شودابتدا یک myappجدید ایجاد می کنیمو app جدید به پروژه اضافه می کنیمسپس نسبت migrate اولیه پروژه اقدام می کنیمو نسبت به ایجاد سوپر کاربر اقدام می کنیم:سپس به روش ذیل به دیتابیس SQLLite وصل می شویم سپس فایل SQLite را از مسیر پروژه باز می کنیمسپس مطمن می شویم که سوپر کاربر ایجاد شده استسپس از طریق Django Admin وارد پانل ادمین جنگو می شویم:در نهایت پانل ادمین به شرح زیر قابل مشاهده خواهد بود:Creating Table in Database using Modelابتدا یک پایگاه داده نمونه با استفاده از مدل جنگو ایجاد می کنیم که شامل مقداری داده است و کوئری را روی آن پایگاه داده اجرا می کنیم.برای این کار وارد فایل ماژول مربوط به app جدید می شویم:model.py# Create your models here.
class Student(models.Model):
         username = models.CharField(max_length=20)
         first_name = models.CharField(max_length=30)
          last_name = models.CharField(max_length=30)
          mobile = models.CharField(max_length=10)
          email = models.EmailField()

def __str__(self):
             return &amp;quot%s %s&amp;quot % (self.first_name, self.last_name)و سپس دستور زیر را در کنسول manage.py اجرا کنید.python manage.py makemigrationspython manage.py migrateسپس نسبت اضافه کردن مدل جدید به Admi جنگو به شکل زیر اقدام می کنیم:اگر دقت کنید مدل دانشجو به پنل ادمین جنگو اضافه گردید:و نسبت به درج چندین رکورد در این مدل به شرح ذیل اقدام می کنیمما قرار است پرس و جو را اجرا کنیم.How to get all records from table(Model)ما یک مدل داریم به نام دانشجو. برای دریافت تمام رکوردها از مدل، از Student.objects.all() استفاده می کنیم. برای انجام این کار، Shell جنگو را برای اجرای پرس و جو باز کنید.ممکن است تعجب کنید که جنگو ORM چگونه پرس و جوهای ما را اجرا می کند یا کد مربوط به کدی که می نویسیم چیست. دریافت پرس و جوی SQL بسیار ساده است، ما باید از str() استفاده کنیم و آبجکت queryset را همراه با پرس و جو ارسال کنیم.Corresponding SQL QueryHow to add record to table(Model)ما از Student.objects.create() استفاده می کنیم و فیلدها را به همراه مقدار آن به عنوان آرگومان ارسال می کنیم. بیایید مثال زیر را ببینیم.توجه داشته باشید که برای ذخیره رکورد جدید ایجاد شده در جدول، باید از متد .save() روی آبجکت query استفاده کنیم، در غیر این صورت در پایگاه داده نمایش داده نخواهد شد.Retrieving Single Objects from QuerySetsفرض کنید برای تطبیق نتیجه به یک شی خاص از یک مجموعه کوئری نیاز داریم. می توانیم این کار را با استفاده از متد get() انجام دهیم. get() مستقیماً شی واحد را برمی گرداند. بیایید مثال زیر را ببینیم.مثال دوم:همانطور که در هر دو مثال می بینیم، شی واحد را دریافت می کنیم نه مجموعه پرس و جو از یک شی واحد. اگر نتیجه ای وجود نداشته باشد، با پرس و جو مطابقت داشته باشید، get() یک استثنای DoesNotExist را ایجاد می کند. از طرف دیگر، اگر چندین فیلد منطبق وجود داشته باشد، MultipleObjectReturned را افزایش می دهد که یک ویژگی از خود کلاس مدل است.مثالDoesNotExist :مثال MultipleObjectReturned:Filtering the Recordsدر مثال قبلی، QuerySet برگردانده شده توسط all() رکورد all را در جدول پایگاه داده توصیف می کند. اما گاهی لازم است زیرمجموعه مجموعه کامل شی را انتخاب کنیم و با افزودن شرایط فیلتر می توان این کار را انجام دادنکته - تفاوت بین متد get() و filter() در این است که متد filter() مجموعه query شی(ها) را برمی گرداند که در آن متد get() یک شی را برمی گرداند.Using exclude() Methodیک QuerySet جدید حاوی اشیایی را برمی گرداند که با پارامتر جستجوی داده شده مطابقت ندارند. به عبارت دیگر، رکوردها را با توجه به شرایط جستجو حذف کرد. بیایید مثال زیر را درک کنیمHow to make OR queries in Django ORM?عملیات OR زمانی انجام می شود که به فیلترینگ رکورد با دو یا چند شرط نیاز داشته باشیم. در مثال زیر، دانش‌آموزی را دریافت می‌کنیم که نامش با «A» و نام خانوادگی‌اش با «M» شروع می‌شود.Django allows us to do this in two ways.queryset_1 |queryset_2filter(Q(&lt;condition_1&gt;) | Q(&lt;condition_2&gt;Creating Multiple Object in One Shotگاهی اوقات می خواهیم چندین شی را در یک shot ایجاد کنیم. فرض کنید می خواهیم یکباره اشیاء جدیدی ایجاد کنیم و نمی خواهیم چندین کوئری را در پایگاه داده اجرا کنیم.  bulk_create را برای ایجاد چندین شی به یک روش فراهم می کندfrom myapp.models import Student
Student.objects.all().count()  
3
Student.objects.bulk_create([Student(first_name=&#039;fn1&#039;,last_name=&#039;ln1&#039;,mobile=&#039;0914&#039;,email=&#039;fn1@test.com&#039;),Student(first_name=&#039;fn2&#039;,last_name=&#039;ln2&#039;,mobile=&#039;0913&#039;,email=&#039;fn2@test.com&#039;)])

[&lt;Student: fn1 ln1&gt;, &lt;Student: fn2 ln2&gt;]
Student.objects.all().count() 

5Limiting QuerySetsما می‌توانیم با استفاده از دستور برش فهرست پایتون، محدودیت را در مجموعه query تنظیم کنیم. این عملیات معادل بندهای LIMIT و OFFSET SQL است. بیایید پرس و جو زیر را ببینیم.جستجوی زیر اولین رکورد تا رکورد پنجم برمی گرداند.دقت شود رکورد از جنگو از رکورد صفر شماره گذاری می شوددقت شود در جنگو Negative indexing پشتیبانی نمی شود. با این حال، ما می توانیم از Stepدر QuerySets استفاده کنیم.How to order a QuerySets in ascending or descending order?جنگو متد order_by را برای مرتب سازی مجموعه query ارائه می دهد. این متد نام فیلدی را می گیرد که می خواهیم نتیجه را مرتب کنیم (صعودی و نزولی). بیایید مثال زیر را ببینیمExample - Ascending orderبرای مرتب سازی نزولی، قبل از فیلد پرس و جو از Not &#x27;-&#x27; استفاده می کنیم.همچنین می توانیم چندین فیلد را در تابع order_by پاس کنیم.How to order on a field from a related model (with foreign key)?حال، یاد خواهیم گرفت که چگونه می توانیم داده ها را در مدل های رابطه ای  واکشی کنیم . مدل دیگری به نام Teacher ایجاد می کنیم که یک مدل مرتبط با مدل Student است.فایل Model پروژه را به شرح ذیل تغییر می دهیم:Models.pyfrom django.db import models


class Teacher(models.Model):
    teacher_name = models.CharField(max_length=200)

    def __str__(self):
        return f&#039;{self.teacher_name}&#039;


class Student(models.Model):
    username = models.CharField(max_length=20)
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    mobile = models.CharField(max_length=10)
    email = models.EmailField()
    teacher = models.ForeignKey(Teacher, blank=True, null=True, on_delete=models.CASCADE)

    def __str__(self):
        return &amp;quot%s %s&amp;quot % (self.first_name, self.last_name)ما معلمان را به مدل دانشجو  اضافه کرده ایم و هر معلم با دانش آموز مرتبط است.حالا اگر بخواهیم از طریق مدل دانشجو اطلاعات معلمان را واکشی کنیم  می توانیم به صورت زیر عمل کنیم.admin.pyfrom django.contrib import admin

# Register your models here.
from myapp.models import Student, Teacher

admin.site.register(Student)
admin.site.register(Teacher)چند تا معلم به جدول Teacher اضافه می کنیمبرای هر کدام از دانشجویان یک معلم اختصاص می دهیم:from myapp.models import Studentq = Student.objects.select_related(&#039;teacher&#039;)print(q.query)SELECT &amp;quotmyapp_student&amp;quot.&amp;quotid&amp;quot, &amp;quotmyapp_student&amp;quot.&amp;quotusername&amp;quot, &amp;quotmyapp_student&amp;quot.&amp;quotfirst_name&amp;quot, &amp;quotmyapp_student&amp;quot.&amp;quotlast_name&amp;quot, &amp;quotmyapp_student&amp;quot.&amp;quotmobile&amp;quot, &amp;quotmyapp_student&amp;quot.&amp;quotemail&amp;quot, &amp;quotmyapp_student&amp;quot.&amp;quotteacher_id&amp;quot, &amp;quotmyapp_teacher&amp;quot.&amp;quotid&amp;quot, &amp;quotmyapp_teacher&amp;quot.&amp;quotteacher_name&amp;quot FROM &amp;quotmyapp_student&amp;quot LEFT OUTER JOIN &amp;quotmyapp_teacher&amp;quot ON (&amp;quotmyapp_student&amp;quot.&amp;quotteacher_id&amp;quot = &amp;quotmyapp_teacher&amp;quot.&amp;quotid&amp;quot)Important Field Lookupsجستجوی فیلد پرس و جو چیزی نیست جز شرطی که همان عبارت SQL WHERE را مشخص می کند. آنها به عنوان آرگومان های کلیدواژه متدهای QuerySet مانند filter()، exclude() و get() بیان می شوند.Example -زمانی که هیچ نوع جستجویی ارائه نمی شود (مانند Entry.objects.get(id=14)) برای راحتی، نوع جستجو exact فرض می شود.exact¶مطابقت کامل. اگر مقدار ارائه شده برای مقایسه None باشد، به عنوان یک SQL NULL تفسیر می شودExamples:Entry.objects.get(id__exact=14)
Entry.objects.get(id__exact=None)SQL equivalents:SELECT ... WHERE id = 14;
SELECT ... WHERE id IS NULL;MySQL comparisonsدر MySQL، تنظیمات «collation» جدول پایگاه داده تعیین می‌کند که آیا مقایسه‌های دقیق به حروف بزرگ و کوچک حساس هستند یا خیر. این یک تنظیمات پایگاه داده است، نه یک تنظیم جنگو. این امکان وجود دارد که جداول MySQL خود را برای استفاده از مقایسه‌های حساس به حروف کوچک و بزرگ پیکربندی کنید، iexact¶تطابق دقیق بدون حساس به حروف کوچک و بزرگ. اگر مقدار ارائه شده برای مقایسه None باشد، به عنوان SQL NULL تفسیر می شودExample:Blog.objects.get(name__iexact=&#039;beatles blog&#039;)
Blog.objects.get(name__iexact=None)SQL equivalents:SELECT ... WHERE name ILIKE &#039;beatles blog&#039;;
SELECT ... WHERE name IS NULL;Note the first query will match &#x27;Beatles Blog&#x27;, &#x27;beatles blog&#x27;, &#x27;BeAtLes BLoG&#x27;, etc.SQLite usersهنگام استفاده از باطن SQLite و رشته های غیر ASCII، یادداشت پایگاه داده در مورد مقایسه رشته ها را در نظر داشته باشید. SQLite تطبیق غیرحساس به حروف بزرگ و کوچک برای رشته های غیرASCII انجام نمی دهد.contains¶Case-sensitive containment test.Example:Entry.objects.get(headline__contains=&#039;Lennon&#039;)SQL equivalent:SELECT ... WHERE headline LIKE &#039;%Lennon%&#039;;Note this will match the headline &#x27;Lennon honored today&#x27; but not &#x27;lennon honored today&#x27;.SQLite usersSQLite doesn’t support case-sensitive LIKE statements; contains acts like icontains for SQLite. icontains¶Case-insensitive containment test.Example:Entry.objects.get(headline__icontains=&#039;Lennon&#039;)SQL equivalent:SELECT ... WHERE headline ILIKE &#039;%Lennon%&#039;;SQLite usersWhen using the SQLite backend and non-ASCII strings, bear in mind the database note about string comparisons.in¶In a given iterable; often a list, tuple, or queryset. It’s not a common use case, but strings (being iterables) are accepted.Examples:Entry.objects.filter(id__in=[1, 3, 4])
Entry.objects.filter(headline__in=&#039;abc&#039;)SQL equivalents:SELECT ... WHERE id IN (1, 3, 4);
SELECT ... WHERE headline IN (&#039;a&#039;, &#039;b&#039;, &#039;c&#039;);You can also use a queryset to dynamically evaluate the list of values instead of providing a list of literal values:inner_qs = Blog.objects.filter(name__contains=&#039;Cheddar&#039;)
entries = Entry.objects.filter(blog__in=inner_qs)This queryset will be evaluated as subselect statement:SELECT ... WHERE blog.id IN (SELECT id FROM ... WHERE NAME LIKE &#039;%Cheddar%&#039;)If you pass in a QuerySet resulting from values() or values_list() as the value to an __in lookup, you need to ensure you are only extracting one field in the result. For example, this will work (filtering on the blog names):inner_qs = Blog.objects.filter(name__contains=&#039;Ch&#039;).values(&#039;name&#039;)
entries = Entry.objects.filter(blog__name__in=inner_qs)This example will raise an exception, since the inner query is trying to extract two field values, where only one is expected:# Bad code! Will raise a TypeError.
inner_qs = Blog.objects.filter(name__contains=&#039;Ch&#039;).values(&#039;name&#039;, &#039;id&#039;)
entries = Entry.objects.filter(blog__name__in=inner_qs)Performance considerationsدر مورد استفاده از پرس و جوهای تو در تو محتاط باشید و ویژگی های عملکرد سرور پایگاه داده خود را درک کنید  برخی از پشتیبان های پایگاه داده، به ویژه MySQL، پرس و جوهای تودرتو را به خوبی بهینه نمی کنند. در این موارد، استخراج لیستی از مقادیر و ارسال آن به کوئری دوم کارآمدتر است. یعنی به جای یک کوئری از دو کوئری استفاده کنید:values = Blog.objects.filter(
        name__contains=&#039;Cheddar&#039;).values_list(&#039;pk&#039;, flat=True)
entries = Entry.objects.filter(blog__in=list(values))startswith¶Case-sensitive starts-with.Example:Entry.objects.filter(headline__startswith=&#039;Lennon&#039;)SQL equivalent:SELECT ... WHERE headline LIKE &#039;Lennon%&#039;;SQLite doesn’t support case-sensitive LIKE statements; startswith acts like istartswith for SQLite.istartswith¶Case-insensitive starts-with.Example:Entry.objects.filter(headline__istartswith=&#039;Lennon&#039;)SQL equivalent:SELECT ... WHERE headline ILIKE &#039;Lennon%&#039;;SQLite usersWhen using the SQLite backend and non-ASCII strings, bear in mind the database note about string comparisons.endswith¶Case-sensitive ends-with.Example:Entry.objects.filter(headline__endswith=&#039;Lennon&#039;)SQL equivalent:SELECT ... WHERE headline LIKE &#039;%Lennon&#039;;SQLite usersSQLite doesn’t support case-sensitive LIKE statements; endswith acts like iendswith for SQLite. Refer to the database note documentation for more.iendswith¶Case-insensitive ends-with.Example:Entry.objects.filter(headline__iendswith=&#039;Lennon&#039;)SQL equivalent:SELECT ... WHERE headline ILIKE &#039;%Lennon&#039;SQLite usersWhen using the SQLite backend and non-ASCII strings, bear in mind the database note about string comparisons.range¶Range test (inclusive).Example:import datetime
start_date = datetime.date(2005, 1, 1)
end_date = datetime.date(2005, 3, 31)
Entry.objects.filter(pub_date__range=(start_date, end_date))SQL equivalent:SELECT ... WHERE pub_date BETWEEN &#039;2005-01-01&#039; and &#039;2005-03-31&#039;;You can use range anywhere you can use BETWEEN in SQL — for dates, numbers and even characters.WarningFiltering a DateTimeField with dates won’t include items on the last day, because the bounds are interpreted as “0am on the given date”. If pub_date was a DateTimeField, the above expression would be turned into this SQL:SELECT ... WHERE pub_date BETWEEN &#039;2005-01-01 00:00:00&#039; and &#039;2005-03-31 00:00:00&#039;;How to group record in Django ORM?جنگو ORM تسهیلات گروه بندی را با استفاده از توابع تجمعی مانند Max، Min، Avg و Sum فراهم می کند. گاهی اوقات ما نیاز داریم که مقادیر کل را از اشیا بدست آوریم. بیایید مثال زیر را درک کنیم.&gt;&gt;&gt; from django.db.models import Avg, Max, Min, Sum, Count
&gt;&gt;&gt; Student.objects.all().aggregate(Avg(&#039;id&#039;))
{&#039;id__avg&#039;: 5.5}
&gt;&gt;&gt; Student.objects.all().aggregate(Min(&#039;id&#039;))
{&#039;id__min&#039;: 1}
&gt;&gt;&gt; Student.objects.all().aggregate(Max(&#039;id&#039;))
{&#039;id__max&#039;: 10}
&gt;&gt;&gt; Student.objects.all().aggregate(Sum(&#039;id&#039;))
{&#039;id__sum&#039;: 55}How to perform truncate like operation using Django ORM?توجه شود truncate  کوتاه کردن در SQL به معنای پاک کردن داده های جدول برای استفاده در آینده است. جنگو متدهای داخلی را برای کوتاه کردن جدول ارائه نمی دهد، اما می توانیم از متد delete() برای به دست آوردن نتیجه مشابه استفاده کنیم. بیایید مثال زیر را درک کنیم.&gt;&gt;&gt; Student.objects.all().count()
5
&gt;&gt;&gt; Student.objects.all().delete()
(5, {&#039;sampleapp.Student&#039;: 5})
&gt;&gt;&gt; Student.objects.all().count()
0
&gt;&gt;&gt; Student.objects.all()
&lt;QuerySet []&gt;How to get union of Dataتوجه شود Union به معنای دریافت رکوردی است که در هر دو مجموعه پرس و جو رایج است. بیایید ببینیم چگونه می توانیم این کار را انجام دهیم.gt¶Greater than.Example:Entry.objects.filter(id__gt=4)SQL equivalent:SELECT ... WHERE id &gt; 4;gte¶Greater than or equal to.lt¶Less than.lte¶Less than or equal to.q1 = Student.objects.filter(id__gte = 15)
&gt;&gt;&gt; q1
&lt;QuerySet [&lt;Student: Megha Bhardwaj&gt;, &lt;Student: Akash Mishra&gt;]&gt;
&gt;&gt;&gt; q2 = Student.objects.filter(id__lte = 15)
&gt;&gt;&gt; q2
&lt;QuerySet [&lt;Student: Ritesh Tiwari&gt;, &lt;Student: Yash Sharma&gt;, &lt;Student: Arpita Sharma&gt;, &lt;Student: Prince Sharma&gt;, &lt;Student: Megha Bhardwaj&gt;]&gt;
&gt;&gt;&gt; q1.union(q2
&lt;QuerySet [&lt;Student: Ritesh Tiwari&gt;, &lt;Student: Yash Sharma&gt;, &lt;Student: Arpita Sharma&gt;, &lt;Student: Prince Sharma&gt;, &lt;Student: Megha Bhardwaj&gt;, &lt;Student: Akash Mishra&gt;]&gt;
What is difference between null=True and blank=True?در جنگو، ما اغلب از null و blank استفاده می کنیم، به طور پیش فرض مقادیر آنها False است. هر دوی این مقادیر در سطح فیلدی کار می کنند که می خواهیم یک فیلد null یا blank نگه داریم. هر دو مقدار مشابه به نظر می رسند اما در استفاده متفاوت هستند.If null=True means the field value is set as NULL i.e. no data. It is basically for the database column value.date = models.DateTimeField(null=True)The blank = True specifies whether field is required in forms.title = models.CharField(blank=True) // title can be kept blank. In the database (&quot;&quot;) will be stored.If we set null=True blank=True, means that the field is optional in all circumstances.teacher = models.ForeignKey(null=True, blank=True) // The exception is CharFields() and TextFields(), which in Django are never saved as ?→NULL. Blank values are stored in the DB as an empty string (&#x27;&#x27;).</description>
                <category>جواد جهانگیری</category>
                <author>جواد جهانگیری</author>
                <pubDate>Sat, 26 Mar 2022 08:35:30 +0430</pubDate>
            </item>
                    <item>
                <title>آموزش جنگو  Django Tutorial</title>
                <link>https://virgool.io/@javadjahangiri/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%D8%AC%D9%86%DA%AF%D9%88-django-tutorial-r80w2wzre8sz</link>
                <description>به نام آن که جان را فکرت آموخت / چراغ دل به نور جان برافروختبا عرض سلام و وقت بخیر خدمت کاربران محترم سایت ویرگول، در این مقاله آموزشی که چکیده آموزش جنگو از سایت tutorialspoint بهمراه مطالب تکمیلی تر , سعی شده یک آموزش کاربردی و پروژه محور از جنگو ارایه گردد.ایده این سری مقاله های آموزشی از این موضوع سرچشمه می گیرد که بخشی از خوانندگان وجود دارد که به محتوای نوشتاری آنلاین بهتر پاسخ می دهند و ترجیج می دهند مهارت های جدید را به سرعت از طریق خواندن افزایش دهند.این سری اموزش ها با ارایه اولین پکیج آموزشی در خصوص مانگودبی آغاز می شود که انتظار می رود با واکنش مثبت کاربران همراه شود.توجه: این مقاله به مرور زمان، ویرایش و یا تکمیل می‌شود!تقاضا: در صورتی که با مشکل تایپی، دستوری و یا مفهومی در این مقاله برخورد کردید، از شما دوست عزیز و گرامی، صمیمانه تقاضا می‌کنم که اینجانب را مطلع کرده، تا نسبت به تصحیح و یا تکمیل آن، در اسرع وقت، اقدام نمایم. با کمال تشکر جواد جهانگیریشماره تلفن همراه: 09149431772نشانی پست الکترونیکی: javad.jahangiri.niopdc@gmail.comفیلم‌های آموزشی در آپارات:جواد جهانگیری (CTO) - آپاراتفیلم آموزشی در یوتویب: javad jahangiri - YouTubeنسخه مقاله: ۱.۱ - تاریخ بروزرسانی: 1400/11/27برای دیدن فیلم اموزشی مربوطه به کانال آپاراتی بنده به ادرس جواد جهانگیری (CTO) - آپارات مراجعه نماییدجواد جهانگیری (CTO) - آپاراتDjango TutorialDjango - Homeجنگو یک چارچوب توسعه وب است که به ساخت و حفظ برنامه های کاربردی وب با کیفیت کمک می کند. جنگو به حذف کارهای تکراری کمک می کند و فرآیند توسعه را به تجربه ای آسان و صرفه جویی در زمان تبدیل می کند. این آموزش درک کاملی از جنگو می دهد.Audienceاین آموزش برای توسعه دهندگانی طراحی شده است که می خواهند یاد بگیرند که چگونه برنامه های کاربردی وب با کیفیت را با استفاده از تکنیک ها و ابزارهای هوشمند ارائه شده توسط جنگو توسعه دهند.Prerequisitesقبل از ادامه، مطمئن شوید که اصول برنامه نویسی رویه ای و شی گرا را درک کرده اید: ساختارهای کنترل، ساختارهای داده و متغیرها، کلاس ها، اشیاء و غیره.Django - Basicsجنگو یک چارچوب وب سطح بالا پایتون است که توسعه سریع و طراحی تمیز و عملی را تشویق می کند. جنگو ساخت برنامه های وب بهتر را به سرعت و با کد کمتر آسان تر می کند.توجه - جنگو یک علامت تجاری ثبت شده بنیاد نرم افزار جنگو است و تحت مجوز BSD tفعالیت می کند.History of Django2003 - توسط Adrian Holovaty و Simon Willison به عنوان یک پروژه داخلی در روزنامه Lawrence Journal-World آغاز شد.2005 - ژوئیه 2005 منتشر شد و نام آن را جنگو به نام جانگو راینهارت، نوازنده گیتار جاز، گذاشت.2005 - به اندازه کافی بالغ شده تا بتواند چندین سایت پر ترافیک را مدیریت کند.کنونی – جنگو اکنون یک پروژه منبع باز با مشارکت کنندگان در سراسر جهان است.Django– فلسفه های طراحیجنگو با فلسفه های طراحی زیر ارائه می شود :Loosely Coupledهدف جنگو این است که هر عنصر Stack خود را مستقل از بقیه کند.Less Codingکد کمتر به نوبه خود توسعه سریع.Don&#x27;t Repeat Yourself (DRY)- همه چیز باید دقیقاً در یک مکان توسعه داده شود به جای تکرار دوباره و دوباره.Fast Developmentفلسفه جنگو این است که تمام تلاش خود را برای تسهیل توسعه سریع انجام دهد.Clean Designجنگو به شدت یک طراحی تمیز را در سراسر کد خود حفظ می کند و پیروی از بهترین شیوه های توسعه وب را آسان می کند.Advantages of Djangoدر اینجا چند مزیت استفاده از جنگو بیان می شود:Object-Relational Mapping (ORM) Supportجنگو پلی بین مدل داده و موتور پایگاه داده فراهم می کند و از مجموعه بزرگی از سیستم های پایگاه داده از جمله MySQL، Oracle، Postgres و غیره پشتیبانی می کند. جنگو همچنین از پایگاه داده NoSQL از طریق فورک جنگو-nonrel پشتیبانی می کند. در حال حاضر، تنها پایگاه داده های NoSQL پشتیبانی شده MongoDB و google app هستندMultilingual Supportجنگو از طریق سیستم بین المللی سازی داخلی خود از وب سایت های چند زبانه پشتیبانی می کند. بنابراین می توانید وب سایت خود را توسعه دهید که از چندین زبان پشتیبانی می کندFramework Supportجنگو دارای پشتیبانی داخلی از Ajax، RSS، Caching و فریمورک های مختلف دیگر است.Administration GUI جنگو یک رابط کاربری خوب و آماده برای استفاده برای فعالیت های اداری ارائه می دهد.Development Environmentجنگو دارای یک وب سرور سبک وزن است تا توسعه و آزمایش برنامه های کاربردی را تسهیل کند.Django - Overviewهمانطور که می دانید جنگو یک چارچوب وب پایتون است. و مانند اکثر فریم ورک های مدرن، جنگو از الگوی MVC پشتیبانی می کند. ابتدا بیایید ببینیم الگوی Model-View-Controller (MVC) چیست و سپس به ویژگی جنگو برای الگوی Model-View-Template (MVT) خواهیم پرداخت.MVC Patternوقتی در مورد برنامه هایی که رابط کاربری (وب یا دسکتاپ) را ارائه می دهند صحبت می کنیم، معمولاً در مورد معماری MVC صحبت می کنیم. و همانطور که از نام آن پیداست، الگوی MVC بر اساس سه جزء است: Model، View و Controller. برای کسب اطلاعات بیشتر، آموزش MVC ما را اینجا ببینید.DJANGO MVC - MVT PatternModel-View-Template (MVT) کمی با MVC متفاوت است. در واقع تفاوت اصلی بین این دو الگو این است که خود جنگو از بخش Controller (کد نرم افزاری که تعاملات بین Model و View را کنترل می کند) مراقبت می کند و الگو را به ما واگذار می کند. این قالب یک فایل HTML است که با زبان قالب جنگو (DTL) ترکیب شده است.نمودار زیر نشان می دهد که چگونه هر یک از اجزای الگوی MVT با یکدیگر تعامل می کنند تا یک درخواست کاربر را ارائه دهند -توسعه‌دهنده مدل، نمای و قالب را ارائه می‌کند و سپس آن را به یک URL نگاشت می‌کند و جنگو کارهای جادویی را برای ارائه آن به کاربر انجام می‌دهد.Django - Environmentمحیط توسعه جنگو شامل نصب و راه اندازی پایتون، جنگو و یک سیستم پایگاه داده است. از آنجایی که جنگو با برنامه های کاربردی وب سر و کار دارد، لازم به ذکر است که شما به راه اندازی وب سرور نیز نیاز دارید.Step 1 – Installing Pythonجنگو با کد 100% خالص پایتون نوشته شده است، بنابراین باید پایتون را روی سیستم خود نصب کنید. آخرین نسخه جنگو به پایتون 2.6.5 یا بالاتر نیاز دارداگر از آخرین توزیع‌های لینوکس یا Mac OS X استفاده می‌کنید، احتمالاً از قبل پایتون را نصب کرده‌اید. می توانید با تایپ دستور پایتون در خط فرمان آن را تأیید کنید. اگر چیزی شبیه به این مشاهده کردید، پس پایتون نصب شده است.$ python
Python 2.7.5 (default, Jun 17 2014, 18:11:42)
[GCC 4.8.2 20140120 (Red Hat 4.8.2-16)] on linux2
در غیر این صورت می توانید آخرین نسخه پایتون را از لینک http://www.python.org/download دانلود و نصب کنید.Step 2 - Installing Djangoنصب جنگو بسیار آسان است، اما مراحل لازم برای نصب آن به سیستم عامل شما بستگی دارد. از آنجایی که پایتون یک زبان مستقل از پلتفرم است، جنگو یک بسته دارد که بدون در نظر گرفتن سیستم عامل شما در همه جا کار می کند.آخرین نسخه جنگو را می توانید از لینک http://www.djangoproject.com/download دانلود کنید.UNIX/Linux and Mac OS X Installationاگر سیستم عامل لینوکس یا مک را اجرا می کنید، دو راه برای نصب جنگو دارید - می توانید از مدیر بسته سیستم عامل خود استفاده کنید یا در صورت نصب از easy_install یا pip استفاده کنید. با استفاده از آرشیو رسمی که قبلا دانلود کرده اید، آن را به صورت دستی نصب کنید. ما گزینه دوم را پوشش خواهیم داد زیرا اولین مورد به توزیع سیستم عامل شما بستگی دارد. اگر تصمیم گرفته اید گزینه اول را دنبال کنید، فقط مراقب نسخه جنگویی که نصب می کنید باشید. فرض کنید بایگانی خود را از لینک بالا دریافت کرده اید، باید چیزی شبیه به Django-x.xx.tar.gz باشد$ tar xzvf Django-x.xx.tar.gz
$ cd Django-x.xx
$ sudo python setup.py installYou can test your installation by running this command$ django-admin.py --versionاگر نسخه فعلی جنگو را روی صفحه نمایش می بینید، همه چیز تنظیم شده است.Windows Installationما فرض می کنیم که بایگانی جنگو و پایتون خود را روی رایانه خود نصب کرده اید.First, PATH verification.در برخی از نسخه های ویندوز (ویندوز 7) ممکن است لازم باشد مطمئن شوید که متغیر Path system مسیر زیر را دارد، البته C:\Python34\;C:\Python34\Lib\site-packages\django\bin\. بسته به نسخه پایتون شماThen, extract and install Django.c:\&gt;cd c:\Django-x.xxسپس، جنگو را با اجرای دستور زیر نصب کنید که برای آن به مجوزهای مدیریتی در پوسته ویندوز &quot;cmd&quot; نیاز دارید -c:\Django-x.xx&gt;python setup.py installبرای آزمایش نصب خود، یک خط فرمان باز کنید و دستور زیر را تایپ کنید -c:\&gt;python -c &amp;quotimport django; print(django.get_version())&amp;quotاگر نسخه فعلی جنگو را روی صفحه نمایش می بینید، همه چیز تنظیم شده است. یا یک دستور cmd را اجرا کنید و python را تایپ کنید و سپس −c:\&gt; python
&gt;&gt;&gt; import django
&gt;&gt;&gt; django.VERSIONStep 3 – Database Setupجنگو از چندین موتور اصلی پایگاه داده پشتیبانی می کند و شما می توانید هر یک از آنها را بر اساس راحتی خود تنظیم کنید.MySQL (http://www.mysql.com/)PostgreSQL (http://www.postgresql.org/)SQLite 3 (http://www.sqlite.org/)Oracle (http://www.oracle.com/)MongoDb (https://django-mongodb-engine.readthedocs.org)GoogleAppEngine Datastore (https://cloud.google.com/appengine/articles/django-nonrel)برای نصب و پیکربندی پایگاه داده دلخواه خود می توانید به مستندات مربوطه مراجعه کنید.توجه - شماره 5 و 6 پایگاه داده NoSQL هستندStep 4 – Web Serverجنگو با یک وب سرور سبک وزن برای توسعه و آزمایش برنامه ها ارائه می شود. این سرور برای کار با جنگو از قبل پیکربندی شده است و مهمتر از آن، هر زمان که کد را تغییر دهید دوباره راه اندازی می شود. با این حال، جنگو از آپاچی و سایر وب سرورهای محبوب مانند Lighttpd پشتیبانی می کند. ما هر دو رویکرد را در فصل های آینده در حین کار با مثال های مختلف مورد بحث قرار خواهیم داد.Django - Creating a Projectحالا که جنگو را نصب کردیم، بیایید شروع به استفاده از آن کنیم. در جنگو، هر برنامه وب که می خواهید ایجاد کنید پروژه نامیده می شود. و یک پروژه مجموعه ای از برنامه های کاربردی است. اپلیکیشن مجموعه ای از فایل های کد است که بر الگوی MVT تکیه دارند. به عنوان مثال فرض کنید می خواهیم یک وب سایت بسازیم، وب سایت پروژه ما است و انجمن، اخبار، موتور تماس برنامه های کاربردی هستند. این ساختار جابجایی یک برنامه را بین پروژه ها آسان تر می کند زیرا هر برنامه مستقلی است.Create a Projectچه در ویندوز یا لینوکس هستید، فقط یک ترمینال یا یک دستور cmd دریافت کنید و به مکانی که می خواهید پروژه شما ایجاد شود بروید، سپس از این کد استفاده کنید -$ django-admin startproject myprojectاین یک پوشه &quot;myproject&quot; با ساختار زیر ایجاد می کند:myproject/
   manage.py
   myproject/
      __init__.py
      settings.py
      urls.py
      wsgi.pyThe Project Structureپوشه &quot;myproject&quot; فقط محفظه پروژه شماست، در واقع شامل دو عنصر - استmanage.pyاین فایل نوعی django-admin محلی پروژه شما برای تعامل با پروژه شما از طریق خط فرمان (راه اندازی سرور توسعه، همگام سازی db...) است. برای دریافت لیست کامل دستورات قابل دسترسی از طریق manager.py می توانید از کد − استفاده کنید$ python manage.py helpThe “myproject” subfolder − این پوشه بسته پایتون واقعی پروژه شما است. شامل چهار فایل:__init__.py − فقط برای پایتون، این پوشه را به عنوان بسته در نظر بگیرید.settings.py − همانطور که از نام آن مشخص است، تنظیمات پروژه شما.urls.py − همه پیوندهای پروژه شما و عملکردی که باید فراخوانی کنید. نوعی ToC پروژه شما.wsgi.py −اگر نیاز به استقرار پروژه خود بر روی WSGI دارید.Setting Up Your Projectپروژه شما در زیر پوشه myproject/settings.py تنظیم شده است. در زیر چند گزینه مهم وجود دارد که ممکن است نیاز به تنظیم داشته باشید -DEBUG = Trueاین گزینه به شما امکان می دهد تعیین کنید که آیا پروژه شما در حالت اشکال زدایی است یا خیر. حالت Debug به شما امکان می دهد اطلاعات بیشتری در مورد خطای پروژه خود دریافت کنید. هرگز آن را برای یک پروژه زنده روی &quot;True&quot; تنظیم نکنید. با این حال، اگر می‌خواهید سرور Django light فایل‌های استاتیک را ارائه دهد، باید روی «درست» تنظیم شود. این کار را فقط در حالت توسعه انجام دهید.DATABASES = {
   &#039;default&#039;: {
      &#039;ENGINE&#039;: &#039;django.db.backends.sqlite3&#039;,
      &#039;NAME&#039;: &#039;database.sql&#039;,
      &#039;USER&#039;: &#039;&#039;,
      &#039;PASSWORD&#039;: &#039;&#039;,
      &#039;HOST&#039;: &#039;&#039;,
      &#039;PORT&#039;: &#039;&#039;,
   }
}پایگاه داده در فرهنگ لغت &quot;پایگاه داده&quot; تنظیم شده است. مثال بالا برای موتور SQLite است. همانطور که قبلا گفته شد، جنگو از − نیز پشتیبانی می کندMySQL (django.db.backends.mysql)PostGreSQL (django.db.backends.postgresql_psycopg2)Oracle (django.db.backends.oracle) and NoSQL DBMongoDB (django_mongodb_engine)قبل از تنظیم هر موتور جدید، مطمئن شوید که درایور صحیح db را نصب کرده اید.همچنین می توانید گزینه های دیگری مانند:TIME_ZONE, LANGUAGE_CODE, TEMPLATE…اکنون که پروژه شما ایجاد و پیکربندی شده است، مطمئن شوید که کار می کند -$ python manage.py runserverبا اجرای کد بالا چیزی شبیه به زیر دریافت خواهید کردValidating models...

0 errors found
September 03, 2015 - 11:41:50
Django version 1.6.11, using settings &#039;myproject.settings&#039;
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.Django - Apps Life Cycleیک پروژه مجموعه ای از برنامه های کاربردی زیاد است. هر برنامه یک هدف دارد و می تواند مجدداً در پروژه دیگری استفاده شود، مانند فرم تماس در یک وب سایت می تواند یک برنامه کاربردی باشد و می تواند برای دیگران استفاده مجدد شود. آن را به عنوان یک ماژول از پروژه خود ببینید.Create an Applicationما فرض می کنیم که شما در پوشه پروژه خود هستید. در پوشه اصلی &quot;myproject&quot; ما، همان پوشه و سپس manager.py −$ python manage.py startapp myappشما به تازگی برنامه myapp را ایجاد کرده اید و مانند پروژه، جنگو یک پوشه &quot;myapp&quot; با ساختار برنامه ایجاد می کند -myapp/
   __init__.py
   admin.py
   models.py
   tests.py
   views.py__init__.py − فقط برای اینکه مطمئن شوید پایتون این پوشه را به عنوان یک بسته مدیریت می کند.admin.py − این فایل به شما کمک می کند تا برنامه را در رابط مدیریت قابل تغییر کنید.models.py − این جایی است که تمام مدل های برنامه ذخیره می شوند.tests.py − این جایی است که آزمون های واحد شما قرار دارد.views.py − نماهای برنامه شما اینجاست.Get the Project to Know About Your Applicationدر این مرحله ما برنامه &quot;myapp&quot; خود را داریم، اکنون باید آن را با پروژه جنگو &quot;myproject&quot; خود ثبت کنیم. برای انجام این کار، INSTALLED_APPS tuple را در فایل settings.py پروژه خود به روز کنید (نام برنامه خود را اضافه کنید) -INSTALLED_APPS = (
   &#039;django.contrib.admin&#039;,
   &#039;django.contrib.auth&#039;,
   &#039;django.contrib.contenttypes&#039;,
   &#039;django.contrib.sessions&#039;,
   &#039;django.contrib.messages&#039;,
   &#039;django.contrib.staticfiles&#039;,
   &#039;myapp&#039;,
)Django - Admin Interfaceجنگو یک رابط کاربری آماده برای استفاده برای فعالیت های اداری ارائه می دهد. همه ما می دانیم که چگونه یک رابط مدیر برای یک پروژه وب مهم است. جنگو به طور خودکار رابط کاربری مدیریت را بر اساس مدل های پروژه شما ایجاد می کند.Starting the Admin Interfaceرابط مدیریت به ماژول django.countrib بستگی دارد. برای اینکه کار کند، باید مطمئن شوید که برخی از ماژول‌ها در INSTALLED_APPS و MIDDLEWARE_CLASSES فایل myproject/settings.py وارد شده‌اند.For INSTALLED_APPS make sure you have −INSTALLED_APPS = (
   &#039;django.contrib.admin&#039;,
   &#039;django.contrib.auth&#039;,
   &#039;django.contrib.contenttypes&#039;,
   &#039;django.contrib.sessions&#039;,
   &#039;django.contrib.messages&#039;,
   &#039;django.contrib.staticfiles&#039;,
   &#039;myapp&#039;,
)For MIDDLEWARE_CLASSES −MIDDLEWARE_CLASSES = (
   &#039;django.contrib.sessions.middleware.SessionMiddleware&#039;,
   &#039;django.middleware.common.CommonMiddleware&#039;,
   &#039;django.middleware.csrf.CsrfViewMiddleware&#039;,
   &#039;django.contrib.auth.middleware.AuthenticationMiddleware&#039;,
   &#039;django.contrib.messages.middleware.MessageMiddleware&#039;,
   &#039;django.middleware.clickjacking.XFrameOptionsMiddleware&#039;,
)قبل از راه اندازی سرور خود، برای دسترسی به رابط مدیریت خود، باید پایگاه داده را راه اندازی کنید -$ python manage.py migratesyncdb جداول یا مجموعه های لازم را بسته به نوع db شما ایجاد می کند، که برای اجرای رابط مدیریت لازم است. حتی اگر سوپرکاربر نداشته باشید، از شما خواسته می شود که یکی را ایجاد کنید.اگر قبلاً یک ابرکاربر دارید یا آن را فراموش کرده‌اید، همیشه می‌توانید با استفاده از کد زیر یکی ایجاد کنید$ python manage.py createsuperuserاکنون برای شروع رابط مدیریت، باید مطمئن شویم که یک URL برای رابط مدیریت خود پیکربندی کرده ایم. myproject را باز کنیدfrom django.conf.urls import patterns, include, url

from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns(&#039;&#039;,
   # Examples:
   # url(r&#039;^$&#039;, &#039;myproject.views.home&#039;, name = &#039;home&#039;),
   # url(r&#039;^blog/&#039;, include(&#039;blog.urls&#039;)),

   url(r&#039;^admin/&#039;, include(admin.site.urls)),
)Now just run the server.$ python manage.py runserverAnd your admin interface is accessible at: http://127.0.0.1:8000/admin/Once connected with your superuser account, you will see the following screen −این رابط به شما امکان می دهد گروه ها و کاربران جنگو و همه مدل های ثبت شده در برنامه خود را مدیریت کنید. این رابط به شما این توانایی را می دهد که حداقل عملیات CRUD (ایجاد، خواندن، به روز رسانی، حذف) را روی مدل های خود انجام دهید.Django - Creating Viewsتابع view یا به اختصار &quot;view&quot; به سادگی یک تابع پایتون است که یک درخواست وب را می گیرد و یک پاسخ وب را برمی گرداند. این پاسخ می تواند محتویات HTML یک صفحه وب، یا تغییر مسیر، یا یک خطای 404، یا یک سند XML، یا یک تصویر و غیره باشد. مثال: شما از view برای ایجاد صفحات وب استفاده می کنید، توجه داشته باشید که باید یک نما را مرتبط کنید. به یک URL برای دیدن آن به عنوان یک صفحه وب. در جنگو، نماها باید در فایل views.py برنامه ایجاد شوند.Simple Viewما یک نمای ساده در myapp ایجاد می کنیم تا بگوییم &quot;به برنامه من خوش آمدید!&quot;See the following view −from django.http import HttpResponse

def hello(request):
   text = &amp;quot&amp;quot&amp;quot&lt;h1&gt;welcome to my app !&lt;/h1&gt;&amp;quot&amp;quot&amp;quot
   return HttpResponse(text)در این نما، ما از HttpResponse برای رندر HTML استفاده می‌کنیم (همانطور که احتمالاً متوجه شده‌اید که HTML به صورت سخت در نما کدگذاری شده است). برای دیدن این نما به عنوان یک صفحه، فقط باید آن را به یک URL ترسیم کنیم (این مورد در فصل آینده مورد بحث قرار خواهد گرفت).ما از HttpResponse برای رندر HTML در نمای قبلی استفاده کردیم. این بهترین راه برای رندر صفحات نیست. جنگو از الگوی MVT پشتیبانی می کند، بنابراین برای ایجاد نمای قبلی، مانند جنگو - MVT، به آن نیاز داریم -A template: myapp/templates/hello.htmlAnd now our view will look like −from django.shortcuts import render

def hello(request):
   return render(request, &amp;quotmyapp/template/hello.html&amp;quot, {})Views can also accept parameters −from django.http import HttpResponse

def hello(request, number):
   text = &amp;quot&lt;h1&gt;welcome to my app number %s!&lt;/h1&gt;&amp;quot% number
   return HttpResponse(text)هنگامی که به یک URL پیوند داده می شود، صفحه شماره ارسال شده را به عنوان پارامتر نمایش می دهد. توجه داشته باشید که پارامترها از طریق URL ارسال می شوند (در فصل بعدی بحث شده است).Django - URL Mappingاکنون که یک نمای کاری داریم همانطور که در فصل های قبل توضیح داده شد. ما می خواهیم از طریق URL به آن نمای دسترسی پیدا کنیم. جنگو راه خاص خود را برای نقشه برداری URL دارد و با ویرایش فایل url.py پروژه شما (myproject) انجام می شودfrom django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns(&#039;&#039;,
   #Examples
   #url(r&#039;^$&#039;, &#039;myproject.view.home&#039;, name = &#039;home&#039;),
   #url(r&#039;^blog/&#039;, include(&#039;blog.urls&#039;)),

   url(r&#039;^admin&#039;, include(admin.site.urls)),
)هنگامی که کاربر درخواستی برای صفحه ای در برنامه وب شما می کند، کنترلر جنگو وظیفه جستجوی نمای مربوطه را از طریق فایل url.py می کند و سپس پاسخ HTML یا خطای 404 not found را، در صورتی که پیدا نشد، برمی گرداند. در url.py، مهمترین چیز تاپل &quot;urlpatterns&quot; است. جایی است که شما نگاشت بین URL ها و نماها را تعریف می کنید. نقشه برداری یک تاپل در الگوهای URL مانند - استfrom django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns(&#039;&#039;,
   #Examples
   #url(r&#039;^$&#039;, &#039;myproject.view.home&#039;, name = &#039;home&#039;),
   #url(r&#039;^blog/&#039;, include(&#039;blog.urls&#039;)),

   url(r&#039;^admin&#039;, include(admin.site.urls)),
   url(r&#039;^hello/&#039;, &#039;myapp.views.hello&#039;, name = &#039;hello&#039;),
)خط علامت گذاری شده نشانی اینترنتی را نشان می دهد The pattern −Regexp مطابق با URL مورد نظر برای حل و نقشه برداری. هر چیزی که می تواند با ماژول &#x27;re&#x27; پایتون کار کند برای الگو واجد شرایط است (زمانی که می خواهید پارامترها را از طریق url ارسال کنید مفید است).The python path to the view  - مانند زمانی که یک ماژول را وارد می کنید.The name − برای انجام معکوس کردن URL، باید از الگوهای URL با نام همانطور که در مثال های بالا انجام شد استفاده کنید. پس از اتمام، فقط سرور را برای دسترسی به نمای خود از طریق :http://127.0.0.1/hello راه اندازی کنیدOrganizing Your URLsتا کنون URL ها را در فایل myprojects/url.py ایجاد کرده ایم، اما همانطور که قبلا در مورد جنگو و ایجاد یک برنامه گفته شد، بهترین نکته این بود که بتوانیم از برنامه ها در پروژه های مختلف استفاده مجدد کنیم. اگر همه URL های خود را در فایل &quot;projecturl.py&quot; ذخیره کنید، به راحتی می توانید ببینید مشکل چیست. بنابراین بهترین روش این است که یک &quot;url.py&quot; برای هر برنامه ایجاد کنید و آن را در فایل url.py پروژه های اصلی خود بگنجانید (ما قبلا URL های مدیریت را برای رابط مدیر قرار داده بودیم).چگونه انجام می شود؟ما باید با استفاده از کد زیر یک فایل url.py در myapp ایجاد کنیمfrom django.conf.urls import patterns, include, url

urlpatterns = patterns(&#039;&#039;, url(r&#039;^hello/&#039;, &#039;myapp.views.hello&#039;, name = &#039;hello&#039;),)Then myproject/url.py will change to the following −from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns(&#039;&#039;,
   #Examples
   #url(r&#039;^$&#039;, &#039;myproject.view.home&#039;, name = &#039;home&#039;),
   #url(r&#039;^blog/&#039;, include(&#039;blog.urls&#039;)),

   url(r&#039;^admin&#039;, include(admin.site.urls)),
   url(r&#039;^myapp/&#039;, include(&#039;myapp.urls&#039;)),
)ما همه URL ها را از برنامه myapp اضافه کرده ایم. home.html که از طریق «حالا بیایید تصور کنیم که نمای دیگری در myapp &quot;morning&quot; داریم و می‌خواهیم آن را در myapp ترسیم کنیمfrom django.conf.urls import patterns, include, url

urlpatterns = patterns(&#039;&#039;,
   url(r&#039;^hello/&#039;, &#039;myapp.views.hello&#039;, name = &#039;hello&#039;),
   url(r&#039;^morning/&#039;, &#039;myapp.views.morning&#039;, name = &#039;morning&#039;),
)This can be re-factored to −from django.conf.urls import patterns, include, url

urlpatterns = patterns(&#039;myapp.views&#039;,
   url(r&#039;^hello/&#039;, &#039;hello&#039;, name = &#039;hello&#039;),
   url(r&#039;^morning/&#039;, &#039;morning&#039;, name = &#039;morning&#039;),)همانطور که می بینید، ما اکنون از اولین عنصر تاپل urlpattern خود استفاده می کنیم. این می تواند زمانی مفید باشد که می خواهید نام برنامه خود را تغییر دهید.Sending Parameters to Viewsاکنون می دانیم که چگونه URL را نقشه برداری کنیم، چگونه آنها را سازماندهی کنیم، اکنون اجازه دهید نحوه ارسال پارامترها را به نماها ببینیم. یک نمونه کلاسیک نمونه مقاله است (شما می خواهید به مقاله از طریق &quot; دسترسی داشته باشیدfrom django.shortcuts import render
from django.http import HttpResponse

def hello(request):
   return render(request, &amp;quothello.html&amp;quot, {})

def viewArticle(request, articleId):
   text = &amp;quotDisplaying article Number : %s&amp;quot%articleId
   return HttpResponse(text)ما می خواهیم آن را در myapp/url.py ترسیم کنیم تا بتوانیم از طریق &quot;/myapp/article/articleId&quot; به آن دسترسی داشته باشیم، در &quot;myapp/url.py&quot; به موارد زیر نیاز داریم -from django.conf.urls import patterns, include, url

urlpatterns = patterns(&#039;myapp.views&#039;,
   url(r&#039;^hello/&#039;, &#039;hello&#039;, name = &#039;hello&#039;),
   url(r&#039;^morning/&#039;, &#039;morning&#039;, name = &#039;morning&#039;),
   url(r&#039;^article/(\d+)/&#039;, &#039;viewArticle&#039;, name = &#039;article&#039;),)وقتی جنگو url را ببیند: &quot;/myapp/article/42&quot; پارامترهای &#x27;42&#x27; را به viewArticle view منتقل می کند و در مرورگر خود باید نتیجه زیر را دریافت کنید -from django.shortcuts import render
from django.http import HttpResponse

def hello(request):
   return render(request, &amp;quothello.html&amp;quot, {})

def viewArticle(request, articleId):
   text = &amp;quotDisplaying article Number : %s&amp;quot%articleId
   return HttpResponse(text)

def viewArticle(request, month, year):
   text = &amp;quotDisplaying articles of : %s/%s&amp;quot%(year, month)
   return HttpResponse(text)The corresponding url.py file will look like −from django.conf.urls import patterns, include, url

urlpatterns = patterns(&#039;myapp.views&#039;,
   url(r&#039;^hello/&#039;, &#039;hello&#039;, name = &#039;hello&#039;),
   url(r&#039;^morning/&#039;, &#039;morning&#039;, name = &#039;morning&#039;),
   url(r&#039;^article/(\d+)/&#039;, &#039;viewArticle&#039;, name = &#039;article&#039;),
   url(r&#039;^articles/(\d{2})/(\d{4})&#039;, &#039;viewArticles&#039;, name = &#039;articles&#039;),)اکنون وقتی به &quot;/myapp/articles/12/2006/&quot; می روید، &quot;نمایش مقالات: 2006/12&quot; را دریافت می کنید، اما اگر پارامترها را معکوس کنید، نتیجه مشابهی دریافت نمی کنید.برای جلوگیری از آن، می توان یک پارامتر URL را به پارامتر view پیوند داد. برای آن، url.py ما − خواهد شدfrom django.conf.urls import patterns, include, url

urlpatterns = patterns(&#039;myapp.views&#039;,
   url(r&#039;^hello/&#039;, &#039;hello&#039;, name = &#039;hello&#039;),
   url(r&#039;^morning/&#039;, &#039;morning&#039;, name = &#039;morning&#039;),
   url(r&#039;^article/(\d+)/&#039;, &#039;viewArticle&#039;, name = &#039;article&#039;),
   url(r&#039;^articles/(?P\d{2})/(?P\d{4})&#039;, &#039;viewArticles&#039;, name = &#039;articles&#039;),)Django - Template Systemجنگو امکان جداسازی پایتون و HTML را فراهم می کند، پایتون در view ها و HTML در قالب ها قرار می گیرد. برای پیوند این دو، جنگو به تابع رندر و زبان قالب جنگو متکی است.The Render Functionاین تابع سه پارامتر می گیردRequest −درخواست اولیهThe path to the template − این مسیر مربوط به گزینه TEMPLATE_DIRS در متغیرهای project settings.py است.Dictionary of parameters − دیکشنری که شامل تمام متغیرهای مورد نیاز در قالب است. این متغیر می تواند ایجاد شود یا می توانید از locals() برای ارسال تمام متغیرهای محلی اعلام شده در view استفاده کنید.Django Template Language (DTL)موتور قالب جنگو یک زبان کوچک برای تعریف لایه رو به روی کاربر برنامه ارائه می دهد.Displaying Variablesیک متغیر به این شکل است: {{متغیر}}. الگو با متغیر ارسال شده توسط view در پارامتر سوم تابع رندر جایگزین متغیر می شود. بیایید hello.html خود را برای نمایش تاریخ امروز تغییر دهیم -hello.html&lt;html&gt;
   
   &lt;body&gt;
      Hello World!!!&lt;p&gt;Today is {{today}}&lt;/p&gt;
   &lt;/body&gt;
   
&lt;/html&gt;
Then our view will change to −def hello(request):
   today = datetime.datetime.now().date()
   return render(request, &amp;quothello.html&amp;quot, {&amp;quottoday&amp;quot : today})اکنون پس از دسترسی به URL خروجی زیر را دریافت خواهیم کردHello World!!!
Today is Sept. 11, 2015همانطور که احتمالا متوجه شده اید، اگر متغیر یک رشته نباشد، جنگو از متد __str__ برای نمایش آن استفاده می کند. و با همان اصل می توانید به یک ویژگی شی دسترسی داشته باشید، درست مانند آنچه در پایتون انجام می دهید. به عنوان مثال: اگر بخواهیم تاریخ سال را نمایش دهیم، متغیر من این خواهد بود: {{today.year}}.Filtersآنها به شما کمک می کنند تا متغیرها را در زمان نمایش تغییر دهید. ساختار فیلترها به شکل زیر است:{{var|filters}}.Some examples −{{string|truncatewords:80}} − این فیلتر رشته را کوتاه می کند، بنابراین شما فقط 80 کلمه اول را خواهید دید.{{string|lower}} − رشته را به حروف کوچک تبدیل می کند.{{string|escape|linebreaks}} − از محتویات رشته فرار می کند، سپس شکستگی خط را به برچسب تبدیل می کند.همچنین می توانید پیش فرض را برای یک متغیر تنظیم کنید.Tagsبرچسب‌ها به شما امکان می‌دهند عملیات زیر را انجام دهید: if condition، برای حلقه، وراثت الگو و موارد دیگر.Tag ifبرچسب‌ها به شما امکان می‌دهند عملیات زیر را انجام دهید: if condition، برای حلقه، وراثت الگو و موارد دیگر.&lt;html&gt;
   &lt;body&gt;
   
      Hello World!!!&lt;p&gt;Today is {{today}}&lt;/p&gt;
      We are
      {% if today.day == 1 %}
      
      the first day of month.
      {% elif today.day == 30 %}
      
      the last day of month.
      {% else %}
      
      I don&#039;t know.
      {%endif%}
      
   &lt;/body&gt;
&lt;/html&gt;در این قالب جدید، بسته به تاریخ روز، قالب مقدار مشخصی را ارائه می دهد.Tag forدقیقاً مانند «if»، تگ «for» را داریم که دقیقاً مانند پایتون کار می کند. بیایید نمای hello خود را تغییر دهیم تا لیستی را به الگوی خود منتقل کنیم -def hello(request):
   today = datetime.datetime.now().date()
   
   daysOfWeek = [&#039;Mon&#039;, &#039;Tue&#039;, &#039;Wed&#039;, &#039;Thu&#039;, &#039;Fri&#039;, &#039;Sat&#039;, &#039;Sun&#039;]
   return render(request, &amp;quothello.html&amp;quot, {&amp;quottoday&amp;quot : today, &amp;quotdays_of_week&amp;quot : daysOfWeek})The template to display that list using {{ for }} −&lt;html&gt;
   &lt;body&gt;
      
      Hello World!!!&lt;p&gt;Today is {{today}}&lt;/p&gt;
      We are
      {% if today.day == 1 %}
      
      the first day of month.
      {% elif today.day == 30 %}
      
      the last day of month.
      {% else %}
      
      I don&#039;t know.
      {%endif%}
      
      &lt;p&gt;
         {% for day in days_of_week %}
         {{day}}
      &lt;/p&gt;
		
      {% endfor %}
      
   &lt;/body&gt;
&lt;/html&gt;And we should get something like −Hello World!!!
Today is Sept. 11, 2015
We are I don&#039;t know.
Mon
Tue
Wed
Thu
Fri
Sat
SunBlock and Extend Tagsیک سیستم قالب نمی تواند بدون وراثت الگو کامل شود. به این معنی که وقتی قالب های خود را طراحی می کنید، باید یک الگوی اصلی با حفره هایی داشته باشید که الگوی کودک با توجه به نیاز خود آن ها را پر می کند، مانند اینکه ممکن است یک صفحه برای برگه انتخاب شده به css خاصی نیاز داشته باشد.بیایید الگوی hello.html را به ارث بردن از main_template.html تغییر دهیم.main_template.html&lt;html&gt;
   &lt;head&gt;
      
      &lt;title&gt;
         {% block title %}Page Title{% endblock %}
      &lt;/title&gt;
      
   &lt;/head&gt;
	
   &lt;body&gt;
   
      {% block content %}
         Body content
      {% endblock %}
      
   &lt;/body&gt;
&lt;/html&gt;hello.htmlدر مثال بالا، با فراخوانی /myapp/hello، همچنان همان نتیجه قبلی را خواهیم داشت، اما اکنون برای بازگرداندن کد خود به extensions و block تکیه می کنیم.در main_template.html بلوک ها را با استفاده از بلوک تگ تعریف می کنیم. بلوک عنوان حاوی عنوان صفحه و بلوک محتوا محتوای اصلی صفحه خواهد بود. در home.html از extensions برای ارث بردن از main_template.html استفاده می کنیم سپس بلوک تعریف شده در بالا (محتوا و عنوان) را پر می کنیم.Comment Tagتگ کامنت به تعریف نظرات در قالب ها کمک می کند، نه نظرات HTML، آنها در صفحه HTML ظاهر نمی شوند. این می تواند برای مستندسازی یا فقط نظر دادن یک خط کد مفید باشد.Django - Modelsمدل کلاسی است که جدول یا مجموعه را در DB ما نشان می دهد و هر ویژگی کلاس فیلدی از جدول یا مجموعه است. مدل ها در برنامه تعریف شده استCreating a ModelFollowing is a Dreamreal model created as an example −from django.db import models

class Dreamreal(models.Model):

   website = models.CharField(max_length = 50)
   mail = models.CharField(max_length = 50)
   name = models.CharField(max_length = 50)
   phonenumber = models.IntegerField()

   class Meta:
      db_table = &amp;quotdreamreal&amp;quot
هر مدلی از django.db.models.Model ارث می برد. کلاس ما دارای 4 ویژگی (3 CharField و 1 Integer) است که اینها فیلدهای جدول خواهند بود. کلاس Meta با ویژگی db_table به ما امکان می دهد تا جدول یا نام مجموعه واقعی را تعریف کنیم. جنگو به طور خودکار جدول یا مجموعه را نامگذاری می کند: myapp_modelName. این کلاس به شما امکان می دهد نام جدول را به چیزی که دوست دارید مجبور کنید. نوع فیلدهای بیشتری در django.db.models وجود دارد که می توانید در https در مورد آنها اطلاعات بیشتری کسب کنید:$python manage.py syncdbManipulating Data (CRUD)بیایید یک نمای &quot;crudops&quot; ایجاد کنیم تا ببینیم چگونه می توانیم عملیات CRUD را روی مدل ها انجام دهیم. برنامه ماmyapp/views.pyfrom myapp.models import Dreamreal
from django.http import HttpResponse

def crudops(request):
   #Creating an entry
   
   dreamreal = Dreamreal(
      website = &amp;quotwww.polo.com&amp;quot, mail = &amp;quotsorex@polo.com&amp;quot, 
      name = &amp;quotsorex&amp;quot, phonenumber = &amp;quot002376970&amp;quot
   )
   
   dreamreal.save()
   
   #Read ALL entries
   objects = Dreamreal.objects.all()
   res =&#039;Printing all Dreamreal entries in the DB : &lt;br&gt;&#039;
   
   for elt in objects:
      res += elt.name+&amp;quot&lt;br&gt;&amp;quot
   
   #Read a specific entry:
   sorex = Dreamreal.objects.get(name = &amp;quotsorex&amp;quot)
   res += &#039;Printing One entry &lt;br&gt;&#039;
   res += sorex.name
   
   #Delete an entry
   res += &#039;&lt;br&gt; Deleting an entry &lt;br&gt;&#039;
   sorex.delete()
   
   #Update
   dreamreal = Dreamreal(
      website = &amp;quotwww.polo.com&amp;quot, mail = &amp;quotsorex@polo.com&amp;quot, 
      name = &amp;quotsorex&amp;quot, phonenumber = &amp;quot002376970&amp;quot
   )
   
   dreamreal.save()
   res += &#039;Updating entry&lt;br&gt;&#039;
   
   dreamreal = Dreamreal.objects.get(name = &#039;sorex&#039;)
   dreamreal.name = &#039;thierry&#039;
   dreamreal.save()
   
   return HttpResponse(res)Other Data Manipulationبیایید دستکاری های دیگری را که می توانیم روی Models انجام دهیم را بررسی کنیم. توجه داشته باشید که عملیات CRUD بر روی نمونه هایی از مدل ما انجام شد، اکنون ما مستقیماً با کلاسی که مدل ما را نشان می دهد کار خواهیم کرد.Let&#x27;s create a &#x27;datamanipulation&#x27; view in myapp/views.pyfrom myapp.models import Dreamreal
from django.http import HttpResponse

def datamanipulation(request):
   res = &#039;&#039;
   
   #Filtering data:
   qs = Dreamreal.objects.filter(name = &amp;quotpaul&amp;quot)
   res += &amp;quotFound : %s results&lt;br&gt;&amp;quot%len(qs)
   
   #Ordering results
   qs = Dreamreal.objects.order_by(&amp;quotname&amp;quot)
   
   for elt in qs:
      res += elt.name + &#039;&lt;br&gt;&#039;
   
   return HttpResponse(res)Linking ModelsDjango ORM 3 راه برای پیوند مدل ها ارائه می دهد - یکی از اولین مواردی که در اینجا خواهیم دید، روابط یک به چند است. همانطور که در مثال بالا مشاهده می کنید، شرکت Dreamreal می تواند چندین وب سایت آنلاین داشته باشد. تعریف آن رابطه با استفاده از django.db.models.ForeignKey انجام می شودmyapp/models.pyfrom django.db import models

class Dreamreal(models.Model):
   website = models.CharField(max_length = 50)
   mail = models.CharField(max_length = 50)
   name = models.CharField(max_length = 50)
   phonenumber = models.IntegerField()
   online = models.ForeignKey(&#039;Online&#039;, default = 1)
   
   class Meta:
      db_table = &amp;quotdreamreal&amp;quot

class Online(models.Model):
      domain = models.CharField(max_length = 30)
   
   class Meta:
      db_table = &amp;quotonline&amp;quotهمانطور که در myapp/models.py به روز شده مشاهده می کنید، ما مدل آنلاین را اضافه کرده و آن را به مدل Dreamreal خود پیوند دادیم.بیایید بررسی کنیم که چگونه همه اینها از طریق shell manager.py − کار می کنندابتدا اجازه دهید چند شرکت (ورودی های Dreamreal) برای آزمایش در پوسته جنگو ایجاد کنیم -$python manage.py shell

&gt;&gt;&gt; from myapp.models import Dreamreal, Online
&gt;&gt;&gt; dr1 = Dreamreal()
&gt;&gt;&gt; dr1.website = &#039;company1.com&#039;
&gt;&gt;&gt; dr1.name = &#039;company1&#039;
&gt;&gt;&gt; dr1.mail = &#039;contact@company1&#039;
&gt;&gt;&gt; dr1.phonenumber = &#039;12345&#039;
&gt;&gt;&gt; dr1.save()
&gt;&gt;&gt; dr2 = Dreamreal()
&gt;&gt;&gt; dr1.website = &#039;company2.com&#039;
&gt;&gt;&gt; dr2.website = &#039;company2.com&#039;
&gt;&gt;&gt; dr2.name = &#039;company2&#039;
&gt;&gt;&gt; dr2.mail = &#039;contact@company2&#039;
&gt;&gt;&gt; dr2.phonenumber = &#039;56789&#039;
&gt;&gt;&gt; dr2.save()Now some hosted domains −&gt;&gt;&gt; on1 = Online()
&gt;&gt;&gt; on1.company = dr1
&gt;&gt;&gt; on1.domain = &amp;quotsite1.com&amp;quot
&gt;&gt;&gt; on2 = Online()
&gt;&gt;&gt; on2.company = dr1
&gt;&gt;&gt; on2.domain = &amp;quotsite2.com&amp;quot
&gt;&gt;&gt; on3 = Online()
&gt;&gt;&gt; on3.domain = &amp;quotsite3.com&amp;quot
&gt;&gt;&gt; dr2 = Dreamreal.objects.all()[2]
&gt;&gt;&gt; on3.company = dr2
&gt;&gt;&gt; on1.save()
&gt;&gt;&gt; on2.save()
&gt;&gt;&gt; on3.save()دسترسی به ویژگی شرکت میزبان (ورودی Dreamreal) از یک دامنه آنلاین ساده است -&gt;&gt;&gt; on1.company.nameو اگر بخواهیم تمام دامنه آنلاین میزبانی شده توسط یک شرکت در Dreamreal را بدانیم، از کد - استفاده خواهیم کرد&gt;&gt;&gt; dr1.online_set.all()&gt;&gt;&gt; dr1.online_set.all() برای دریافت QuerySet، توجه داشته باشید که تمام روش های دستکاری که قبلا دیده ایم (filter, all, exclude, order_by...) همچنین می توانید به ویژگی های مدل پیوند شده برای عملیات فیلتر دسترسی داشته باشید. می‌گویید که می‌خواهید همه دامنه‌های آنلاینی را که نام Dreamreal حاوی &quot;شرکت&quot; است، دریافت کنید&gt;&gt;&gt; Online.objects.filter(company__name__contains = &#039;company&#039;توجه - این نوع پرس و جو فقط برای SQL DB پشتیبانی می شود. برای DB غیر رابطه ای که در آن Join وجود ندارد و دو &quot;_&quot; وجود دارد، کار نمی کند. اما این تنها راه برای پیوند دادن مدل ها نیست، شما همچنین OneToOneField دارید، پیوندی که تضمین می کند که رابطه بین دو شی منحصر به فرد است. اگر در مثال بالا از OneToOneField استفاده کنیم، به این معنی است که برای هر ورودی Dreamreal فقط یک ورودی آنلاین و از راه دیگر امکان پذیر است. و آخرین مورد، ManyToManyField برای (n-n) رابطه بین جداول. توجه داشته باشید، این موارد مربوط به DB مبتنی بر SQL هستند.Django - Page Redirectionتغییر مسیر صفحه به دلایل زیادی در برنامه وب مورد نیاز است. ممکن است بخواهید زمانی که یک عمل خاص اتفاق می افتد یا اساساً در صورت بروز خطا، کاربر را به صفحه دیگری هدایت کنید. به عنوان مثال، هنگامی که کاربر وارد وب سایت شما می شود، اغلب به صفحه اصلی اصلی یا داشبورد شخصی خود هدایت می شود. در جنگو، تغییر مسیر با استفاده از روش &#x27;redirect&#x27; انجام می شود.متد &#x27;redirect&#x27; به عنوان آرگومان در نظر گرفته می‌شود: نشانی اینترنتی که می‌خواهید به عنوان نام یک view&#x27;s name به آن هدایت شود.The myapp/views looks like the following so far −def hello(request):
   today = datetime.datetime.now().date()
   daysOfWeek = [&#039;Mon&#039;, &#039;Tue&#039;, &#039;Wed&#039;, &#039;Thu&#039;, &#039;Fri&#039;, &#039;Sat&#039;, &#039;Sun&#039;]
   return render(request, &amp;quothello.html&amp;quot, {&amp;quottoday&amp;quot : today, &amp;quotdays_of_week&amp;quot : daysOfWeek})
	
def viewArticle(request, articleId):
   &amp;quot&amp;quot&amp;quot A view that display an article based on his ID&amp;quot&amp;quot&amp;quot
   text = &amp;quotDisplaying article Number : %s&amp;quot %articleId
   return HttpResponse(text)
	
def viewArticles(request, year, month):
   text = &amp;quotDisplaying articles of : %s/%s&amp;quot%(year, month)
   return HttpResponse(text)Let&#x27;s change the hello view to redirect to djangoproject.com and our viewArticle to redirect to our internal &#x27;/myapp/articles&#x27;. To do so the myapp/view.py will change tofrom django.shortcuts import render, redirect
from django.http import HttpResponse
import datetime

# Create your views here.
def hello(request):
   today = datetime.datetime.now().date()
   daysOfWeek = [&#039;Mon&#039;, &#039;Tue&#039;, &#039;Wed&#039;, &#039;Thu&#039;, &#039;Fri&#039;, &#039;Sat&#039;, &#039;Sun&#039;]
   return redirect(&amp;quothttps://www.djangoproject.com&amp;quot)
	
def viewArticle(request, articleId):
   &amp;quot&amp;quot&amp;quot A view that display an article based on his ID&amp;quot&amp;quot&amp;quot
   text = &amp;quotDisplaying article Number : %s&amp;quot %articleId
   return redirect(viewArticles, year = &amp;quot2045&amp;quot, month = &amp;quot02&amp;quot)
	
def viewArticles(request, year, month):
   text = &amp;quotDisplaying articles of : %s/%s&amp;quot%(year, month)
   return HttpResponse(text)در مثال بالا، ابتدا ریدایرکت را از django.shortcuts وارد کردیم و برای تغییر مسیر به وب سایت رسمی جنگو، فقط URL کامل را به روش &#x27;redirect&#x27; به عنوان رشته ارسال می کنیم و برای مثال دوم (نمای viewArticle) &#x27;redirect&#x27; را ارسال می کنیم. متد نام view و پارامترهای آن را به عنوان آرگومان می گیرد.Accessing /myapp/hello, will give you the following screenAnd accessing /myapp/article/42, will give you the following screen −همچنین می توان با افزودن پارامتر دائمی = True مشخص کرد که &#x27;redirect&#x27; موقت است یا دائم. کاربر هیچ تفاوتی نمی بیند، اما اینها جزئیاتی هستند که موتورهای جستجو هنگام رتبه بندی وب سایت شما در نظر می گیرند.همچنین به یاد داشته باشید که پارامتر &quot;name&quot; را در url.py خود در حین نگاشت URL ها تعریف کردیم -url(r&#039;^articles/(?P\d{2})/(?P\d{4})/&#039;, &#039;viewArticles&#039;, name = &#039;articles&#039;),این نام (در اینجا مقاله) می تواند به عنوان استدلال برای روش &#x27;redirect&#x27; استفاده شود، سپس تغییر مسیر viewArticle ما می تواند ازdef viewArticle(request, articleId):
   &amp;quot&amp;quot&amp;quot A view that display an article based on his ID&amp;quot&amp;quot&amp;quot
   text = &amp;quotDisplaying article Number : %s&amp;quot %articleId
   return redirect(viewArticles, year = &amp;quot2045&amp;quot, month = &amp;quot02&amp;quot)TOdef viewArticle(request, articleId):
   &amp;quot&amp;quot&amp;quot A view that display an article based on his ID&amp;quot&amp;quot&amp;quot
   text = &amp;quotDisplaying article Number : %s&amp;quot %articleId
   return redirect(articles, year = &amp;quot2045&amp;quot, month = &amp;quot02&amp;quot)توجه - همچنین یک تابع برای تولید URL وجود دارد. از آن به همان شیوه تغییر مسیر استفاده می شود. روش &quot;reverse&quot; (django.core.urlresolvers.reverse). این تابع یک شی HttpResponseRedirect را بر نمی گرداند، بلکه فقط یک رشته حاوی URL به نمای کامپایل شده با هر آرگومان ارسال شده است.Django - Sending E-mailsجنگو با یک موتور سبک آماده و آسان برای ارسال ایمیل ارائه می شود. مشابه پایتون شما فقط نیاز به واردات smtplib دارید. در جنگو فقط باید django.core.mail را وارد کنید. برای شروع ارسال ایمیل، فایل settings.py پروژه خود را ویرایش کرده و گزینه های زیر را تنظیم کنیدEMAIL_HOST − smtp server.EMAIL_HOST_USER − Login credential for the smtp server.EMAIL_HOST_PASSWORD − Password credential for the smtp server.EMAIL_PORT − smtp server port.EMAIL_USE_TLS or _SSL − True if secure connection.Sending a Simple E-mailLet&#x27;s create a &quot;sendSimpleEmail&quot; view to send a simple e-mail.from django.core.mail import send_mail
from django.http import HttpResponse

def sendSimpleEmail(request,emailto):
   res = send_mail(&amp;quothello paul&amp;quot, &amp;quotcomment tu vas?&amp;quot, &amp;quotpaul@polo.com&amp;quot, [emailto])
   return HttpResponse(&#039;%s&#039;%res)
در اینجا جزئیات پارامترهای send_mail - آمده استsubject − E-mail subject.message − E-mail body.from_email − E-mail from.recipient_list − List of receivers’ e-mail address.fail_silently − Bool, if false send_mail will raise an exception in case of error.auth_user − User login if not set in settings.py.auth_password − User password if not set in settings.py.connection − E-mail backend.html_message − (new in Django 1.7) if present, the e-mail will be multipart/alternativLet&#x27;s create a URL to access our view −from django.conf.urls import patterns, urlurlpatterns = paterns(&#x27;myapp.views&#x27;, url(r&#x27;^simpleemail/(?P&lt;emailto&gt;   [\w.%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4})/&#x27;,    &#x27;sendSimpleEmail&#x27; , name = &#x27;sendSimpleEmail&#x27;),)So when accessing /myapp/simpleemail/polo@gmail.com, you will get the following page −Sending Multiple Mails with send_mass_mailاین روش تعداد پیام هایی که با موفقیت تحویل داده شده است را برمی گرداند. این همان send_mail است اما یک پارامتر اضافی می گیرد. datatuple، نمای sendMassEmail ما پس از آن − خواهد بودfrom django.core.mail import send_mass_mail
from django.http import HttpResponse

def sendMassEmail(request,emailto):
   msg1 = (&#039;subject 1&#039;, &#039;message 1&#039;, &#039;polo@polo.com&#039;, [emailto1])
   msg2 = (&#039;subject 2&#039;, &#039;message 2&#039;, &#039;polo@polo.com&#039;, [emailto2])
   res = send_mass_mail((msg1, msg2), fail_silently = False)
   return HttpResponse(&#039;%s&#039;%res)Let&#x27;s create a URL to access our view −rom django.conf.urls import patterns, url

urlpatterns = paterns(&#039;myapp.views&#039;, url(r&#039;^massEmail/(?P&lt;emailto1&gt;
   [\w.%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4})/(?P&lt;emailto2&gt;
   [\w.%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4})&#039;, &#039;sendMassEmail&#039; , name = &#039;sendMassEmail&#039;),)
When accessing /myapp/massemail/polo@gmail.com/sorex@gmail.com/, we get −send_mass_mail parameters details are −datatuples − A tuple where each element is like (subject, message, from_email, recipient_list).fail_silently − Bool, if false send_mail will raise an exception in case of error.auth_user − User login if not set in settings.py.auth_password − User password if not set in settings.py.connection − E-mail backendهمانطور که در تصویر بالا مشاهده می کنید، دو پیام با موفقیت ارسال شد. توجه - در این مثال ما از سرور اشکال زدایی smtp پایتون استفاده می کنیم که می توانید با استفاده از - راه اندازی کنید.$python -m smtpd -n -c DebuggingServer localhost:1025این بدان معنی است که تمام ایمیل های ارسالی شما در stdout چاپ می شود و سرور ساختگی روی localhost:1025 اجرا می شود.Sending e-mails to admins and managers using mail_admins and mail_managers methodsارسال ایمیل به ادمین ها و مدیران با استفاده از روش های mail_admins و mail_managersADMINS = ((&#x27;polo&#x27;, &#x27;polo@polo.com&#x27;),)MANAGERS = ((&#x27;popoli&#x27;, &#x27;popoli@polo.com&#x27;),)from django.core.mail import mail_admins
from django.http import HttpResponse

def sendAdminsEmail(request):
   res = mail_admins(&#039;my subject&#039;, &#039;site is going down.&#039;)
   return HttpResponse(&#039;%s&#039;%res)کد بالا برای هر مدیری که در قسمت ADMINS تعریف شده است یک ایمیل ارسال می کند.from django.core.mail import mail_managers
from django.http import HttpResponse

def sendManagersEmail(request):
   res = mail_managers(&#039;my subject 2&#039;, &#039;Change date on the site.&#039;)
   return HttpResponse(&#039;%s&#039;%res)کد بالا برای هر مدیری که در قسمت MANAGERS تعریف شده است یک ایمیل ارسال می کند.Parameters details −Subject − E-mail subject.message − E-mail body.fail_silently − Bool, if false send_mail will raise an exception in case of error.connection − E-mail backend.html_message − (new in Django 1.7) if present, the e-mail will be multipart/alternative.Sending HTML E-mailSending HTML message in Django &gt;= 1.7 is as easy as −from django.core.mail import send_mail

from django.http import HttpResponse
   res = send_mail(&amp;quothello paul&amp;quot, &amp;quotcomment tu vas?&amp;quot, &amp;quotpaul@polo.com&amp;quot, 
         [&amp;quotpolo@gmail.com&amp;quot], html_message=&amp;quot)این یک ایمیل چند بخشی/جایگزین تولید می کند.اما برای Django &lt; 1.7 ارسال پیام های HTML از طریق کلاس django.core.mail.EmailMessage و سپس فراخوانی &#x27;send&#x27; روی شی انجام می شود -بیایید یک نمای &quot;sendHTMLEmail&quot; برای ارسال یک ایمیل HTML ایجاد کنیم.from django.core.mail import EmailMessage
from django.http import HttpResponse

def sendHTMLEmail(request , emailto):
   html_content = &amp;quot&lt;strong&gt;Comment tu vas?&lt;/strong&gt;&amp;quot
   email = EmailMessage(&amp;quotmy subject&amp;quot, html_content, &amp;quotpaul@polo.com&amp;quot, [emailto])
   email.content_subtype = &amp;quothtml&amp;quot
   res = email.send()
   return HttpResponse(&#039;%s&#039;%res)
Parameters details for the EmailMessage class creation −Subject − E-mail subject.message − E-mail body in HTML.from_email − E-mail from.to − List of receivers’ e-mail address.bcc − List of “Bcc” receivers’ e-mail address.connection − E-mail backend.Let&#x27;s create a URL to access our view −from django.conf.urls import patterns, url

urlpatterns = paterns(&#039;myapp.views&#039;, url(r&#039;^htmlemail/(?P&lt;emailto&gt;
   [\w.%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4})/&#039;, 
   &#039;sendHTMLEmail&#039; , name = &#039;sendHTMLEmail&#039;),)When accessing /myapp/htmlemail/polo@gmail.com, we get −این کار با استفاده از روش &quot;پیوست&quot; در شی EmailMessage انجام می شود. نمای ارسال ایمیل با پیوست − خواهد بودfrom django.core.mail import EmailMessage
from django.http import HttpResponse

def sendEmailWithAttach(request, emailto):
   html_content = &amp;quotComment tu vas?&amp;quot
   email = EmailMessage(&amp;quotmy subject&amp;quot, html_content, &amp;quotpaul@polo.com&amp;quot, emailto])
   email.content_subtype = &amp;quothtml&amp;quot
   
   fd = open(&#039;manage.py&#039;, &#039;r&#039;)
   email.attach(&#039;manage.py&#039;, fd.read(), &#039;text/plain&#039;)
   
   res = email.send()
   return HttpResponse(&#039;%s&#039;%res)Details on attach arguments −filename − The name of the file to attach.content − The content of the file to attach.mimetype − The attachment&#x27;s content mime type.Django - Generic Viewsدر برخی موارد، نوشتن views، همانطور که قبلاً دیدیم، واقعاً سنگین است. تصور کنید به یک صفحه ثابت یا یک صفحه فهرست نیاز دارید. جنگو یک راه آسان برای تنظیم این نماهای ساده ارائه می دهد که به آن generic views. می گویند. برخلاف classic views، نماهای generic کلاس هستند نه توابع. جنگو مجموعه ای از کلاس ها را برای نماهای عمومی در django.views.generic ارائه می دهد و هر نمای عمومی یکی از آن کلاس ها یا کلاسی است که از یکی از آنها به ارث می رسد.There are 10+ generic classes −&gt;&gt;&gt; import django.views.generic
&gt;&gt;&gt; dir(django.views.generic)

[&#039;ArchiveIndexView&#039;, &#039;CreateView&#039;, &#039;DateDetailView&#039;, &#039;DayArchiveView&#039;, 
   &#039;DeleteView&#039;, &#039;DetailView&#039;, &#039;FormView&#039;, &#039;GenericViewError&#039;, &#039;ListView&#039;, 
   &#039;MonthArchiveView&#039;, &#039;RedirectView&#039;, &#039;TemplateView&#039;, &#039;TodayArchiveView&#039;, 
   &#039;UpdateView&#039;, &#039;View&#039;, &#039;WeekArchiveView&#039;, &#039;YearArchiveView&#039;, &#039;__builtins__&#039;, 
   &#039;__doc__&#039;, &#039;__file__&#039;, &#039;__name__&#039;, &#039;__package__&#039;, &#039;__path__&#039;, &#039;base&#039;, &#039;dates&#039;, 
   &#039;detail&#039;, &#039;edit&#039;, &#039;list&#039;]این را می توانید برای نمای عمومی خود استفاده کنید. بیایید به چند مثال نگاه کنیم تا ببینیم چگونه کار می کند.Static Pagesبیایید یک صفحه استاتیک از قالب &quot;static.html&quot; منتشر کنیم.Our static.html −&lt;html&gt;
   &lt;body&gt; 
      This is a static page!!! 
   &lt;/body&gt;
&lt;/html&gt;If we did that the way we learned before, we would have to change the myapp/views.py to be −from django.shortcuts import render

def static(request):
   return render(request, &#039;static.html&#039;, {})and myapp/urls.py to be −from django.conf.urls import patterns, url

urlpatterns = patterns(&amp;quotmyapp.views&amp;quot, url(r&#039;^static/&#039;, &#039;static&#039;, name = &#039;static&#039;),)The best way is to use generic views. For that, our myapp/views.py will become −from django.views.generic import TemplateView

class StaticView(TemplateView):
   template_name = &amp;quotstatic.html&amp;quotAnd our myapp/urls.py we will be −from myapp.views import StaticView
from django.conf.urls import patterns

urlpatterns = patterns(&amp;quotmyapp.views&amp;quot, (r&#039;^static/$&#039;, StaticView.as_view()),)When accessing /myapp/static you get −For the same result we can also, do the following −No change in the views.pyChange the url.py file to be −from django.views.generic import TemplateView
from django.conf.urls import patterns, url

urlpatterns = patterns(&amp;quotmyapp.views&amp;quot,
   url(r&#039;^static/&#039;,TemplateView.as_view(template_name = &#039;static.html&#039;)),)همانطور که می بینید، فقط باید فایل url.py را در روش دوم تغییر دهید.List and Display Data from DBما قصد داریم تمام ورودی های مدل Dreamreal خود را لیست کنیم. انجام این کار با استفاده از کلاس نمای عمومی ListView آسان می شود. فایل url.py را ویرایش کنید و آن را به صورت - به روز کنیدfrom django.views.generic import ListView
from django.conf.urls import patterns, url

urlpatterns = patterns(
   &amp;quotmyapp.views&amp;quot, url(r&#039;^dreamreals/&#039;, ListView.as_view(model = Dreamreal, 
      template_name = &amp;quotdreamreal_list.html&amp;quot)),
)نکته مهم در این مرحله این است که متغیری که از نمای عمومی به الگو عبور می کند object_list است. اگر می‌خواهید خودتان آن را نام ببرید، باید یک آرگومان context_object_name به متد as_view اضافه کنید. سپس url.py تبدیل به − می شودfrom django.views.generic import ListView
from django.conf.urls import patterns, url

urlpatterns = patterns(&amp;quotmyapp.views&amp;quot,
   url(r&#039;^dreamreals/&#039;, ListView.as_view(
      template_name = &amp;quotdreamreal_list.html&amp;quot)),
      model = Dreamreal, context_object_name = ”dreamreals_objects” ,)The associated template will then be −{% extends &amp;quotmain_template.html&amp;quot %}
{% block content %}
Dreamreals:&lt;p&gt;
{% for dr in object_list %}
{{dr.name}}&lt;/p&gt;
{% endfor %}
{% endblock %}Accessing /myapp/dreamreals/ will produce the following page −Django - Form Processingایجاد فرم در جنگو، واقعا شبیه به ایجاد یک مدل است. در اینجا دوباره فقط باید از کلاس جنگو ارث بری کنیم و ویژگی های کلاس فیلدهای فرم خواهند بود. بیایید یک فایل forms.py را در پوشه myapp اضافه کنیم تا حاوی فرم‌های برنامه ما باشد. ما یک فرم ورود ایجاد خواهیم کرد.myapp/forms.py#-*- coding: utf-8 -*-
from django import forms

class LoginForm(forms.Form):
   user = forms.CharField(max_length = 100)
   password = forms.CharField(widget = forms.PasswordInput())همانطور که در بالا مشاهده شد، نوع فیلد می تواند آرگومان &quot;ویجت&quot; را برای رندر html بگیرد. در مورد ما، ما می خواهیم رمز عبور پنهان باشد، نمایش داده نشود. بسیاری از ویجت های دیگر در جنگو وجود دارند: DateInput برای تاریخ ها، CheckboxInput برای چک باکس ها و غیره.Using Form in a Viewدو نوع درخواست HTTP وجود دارد، GET و POST. در جنگو، شی درخواست ارسال شده به عنوان پارامتر به view شما دارای یک ویژگی به نام &quot;method&quot; است که در آن نوع درخواست تنظیم شده است، و تمام داده های ارسال شده از طریق POST از طریق دیکشنری request.POST قابل دسترسی است.Let&#x27;s create a login view in our myapp/views.py −#-*- coding: utf-8 -*-
from myapp.forms import LoginForm

def login(request):
   username = &amp;quotnot logged in&amp;quot
   
   if request.method == &amp;quotPOST&amp;quot:
      #Get the posted form
      MyLoginForm = LoginForm(request.POST)
      
      if MyLoginForm.is_valid():
         username = MyLoginForm.cleaned_data[&#039;username&#039;]
   else:
      MyLoginForm = Loginform()
		
   return render(request, &#039;loggedin.html&#039;, {&amp;quotusername&amp;quot : username})نمایش، نتیجه فرم ورود ارسال شده از طریق loggedin.html را نمایش می دهد. برای تست آن ابتدا به قالب فرم ورود نیاز داریم. بیایید آن را login.html بنامیم.&lt;html&gt;
   &lt;body&gt;
      
      &lt;form name = &amp;quotform&amp;quot action = &amp;quot{% url &amp;quotmyapp.views.login&amp;quot %}&amp;quot 
         method = &amp;quotPOST&amp;quot &gt;{% csrf_token %}
         
         &lt;div style = &amp;quotmax-width:470px;&amp;quot&gt;
            &lt;center&gt; 
               &lt;input type = &amp;quottext&amp;quot style = &amp;quotmargin-left:20%;&amp;quot 
                  placeholder = &amp;quotIdentifiant&amp;quot name = &amp;quotusername&amp;quot /&gt;
            &lt;/center&gt;
         &lt;/div&gt;
			
         &lt;br&gt;
         
         &lt;div style = &amp;quotmax-width:470px;&amp;quot&gt;
            &lt;center&gt;
               &lt;input type = &amp;quotpassword&amp;quot style = &amp;quotmargin-left:20%;&amp;quot 
                  placeholder = &amp;quotpassword&amp;quot name = &amp;quotpassword&amp;quot /&gt;
            &lt;/center&gt;
         &lt;/div&gt;
			
         &lt;br&gt;
         
         &lt;div style = &amp;quotmax-width:470px;&amp;quot&gt;
            &lt;center&gt; 
            
               &lt;button style = &amp;quotborder:0px; background-color:#4285F4; margin-top:8%;
                  height:35px; width:80%;margin-left:19%;&amp;quot type = &amp;quotsubmit&amp;quot 
                  value = &amp;quotLogin&amp;quot &gt;
                  &lt;strong&gt;Login&lt;/strong&gt;
               &lt;/button&gt;
               
            &lt;/center&gt;
         &lt;/div&gt;
         
      &lt;/form&gt;
      
   &lt;/body&gt;
&lt;/html&gt;این الگو یک فرم ورود به سیستم را نمایش می دهد و نتیجه را در نمای ورود ما در بالا ارسال می کند. احتمالاً متوجه برچسب موجود در قالب شده اید که فقط برای جلوگیری از حمله جعل درخواست متقابل (CSRF) به سایت شما است.{% csrf_token %}هنگامی که ما الگوی ورود به سیستم را داریم، به الگوی loggedin.html نیاز داریم که پس از درمان فرم ارائه می شود.&lt;html&gt;
   
   &lt;body&gt;
      You are : &lt;strong&gt;{{username}}&lt;/strong&gt;
   &lt;/body&gt;
   
&lt;/html&gt;Now, we just need our pair of URLs to get started: myapp/urls.pyfrom django.conf.urls import patterns, url
from django.views.generic import TemplateView

urlpatterns = patterns(&#039;myapp.views&#039;,
   url(r&#039;^connection/&#039;,TemplateView.as_view(template_name = &#039;login.html&#039;)),
   url(r&#039;^login/&#039;, &#039;login&#039;, name = &#039;login&#039;))When accessing &quot;/myapp/connection&quot;, we will get the following login.html template rendered −On the form post, the form is valid. In our case make sure to fill the two fields and you will get −Using Our Own Form ValidationIn the above example, when validating the form −MyLoginForm.is_valid()ما فقط از موتور اعتبار سنجی خود فرم جنگو استفاده کردیم، در مورد ما فقط مطمئن شدیم که فیلدها مورد نیاز هستند. اکنون بیایید سعی کنیم مطمئن شویم که کاربری که قصد ورود به سیستم را دارد در DB ما به عنوان ورودی Dreamreal وجود دارد. برای این کار، myapp را تغییر دهید#-*- coding: utf-8 -*-
from django import forms
from myapp.models import Dreamreal

class LoginForm(forms.Form):
   user = forms.CharField(max_length = 100)
   password = forms.CharField(widget = forms.PasswordInput())

   def clean_message(self):
      username = self.cleaned_data.get(&amp;quotusername&amp;quot)
      dbuser = Dreamreal.objects.filter(name = username)
      
      if not dbuser:
         raise forms.ValidationError(&amp;quotUser does not exist in our db!&amp;quot)
      return usernameحال پس از فراخوانی متد &quot;is_valid&quot;، تنها در صورتی که کاربر در پایگاه داده ما باشد، خروجی صحیح را دریافت خواهیم کرد. اگر می‌خواهید یک فیلد از فرم خود را بررسی کنید، فقط یک روش را که با &quot;clean_&quot; شروع می‌شود، سپس نام فیلد خود را به کلاس فرم خود اضافه کنید. بالا بردن فرم ها. ValidationError مهم است.Django - File Uploadingبه طور کلی برای یک برنامه وب مفید است که بتواند فایل ها (تصویر نمایه، آهنگ ها، pdf، کلمات ...) را آپلود کند. بیایید در این فصل درباره نحوه آپلود فایل ها بحث کنیم.Uploading an Imageقبل از شروع بازی با یک تصویر، مطمئن شوید که کتابخانه تصویر پایتون (PIL) را نصب کرده اید. اکنون برای نشان دادن بارگذاری یک تصویر، بیایید یک فرم نمایه در myapp/forms.py ایجاد کنیم -#-*- coding: utf-8 -*-
from django import forms

class ProfileForm(forms.Form):
   name = forms.CharField(max_length = 100)
   picture = forms.ImageFields()
همانطور که می بینید، تفاوت اصلی در اینجا فقط  forms.ImageField می باشد. ImageField مطمئن می شود که فایل آپلود شده یک تصویر است. در غیر این صورت، اعتبار سنجی فرم ناموفق خواهد بود. اکنون بیایید یک مدل «نمایه» برای ذخیره نمایه آپلود شده خود ایجاد کنیم. این کار در myapp انجام می شوداکنون بیایید یک مدل «نمایه» برای ذخیره نمایه آپلود شده خود ایجاد کنیم. این کار در myapp انجام می شودfrom django.db import models

class Profile&#40;models.Model&#41;:
   name = models.CharField(max_length = 50)
   picture = models.ImageField(upload_to = &#039;pictures&#039;)

   class Meta:
      db_table = &amp;quotprofile&amp;quot
همانطور که برای مدل می بینید، ImageField یک آرگومان اجباری می گیرد: upload_to. این نشان دهنده مکانی روی هارد دیسک است که تصاویر شما در آن ذخیره می شوند. توجه داشته باشید که این پارامتر به گزینه MEDIA_ROOT تعریف شده در فایل settings.py شما اضافه خواهد شد.#-*- coding: utf-8 -*-
from myapp.forms import ProfileForm
from myapp.models import Profile

def SaveProfile&#40;request&#41;:
   saved = False
   
   if request.method == &amp;quotPOST&amp;quot:
      #Get the posted form
      MyProfileForm = ProfileForm(request.POST, request.FILES)
      
      if MyProfileForm.is_valid():
         profile = Profile&#40;&#41;
         profile.name = MyProfileForm.cleaned_data[&amp;quotname&amp;quot]
         profile.picture = MyProfileForm.cleaned_data[&amp;quotpicture&amp;quot]
         profile.save()
         saved = True
   else:
      MyProfileForm = Profileform()
		
   return render(request, &#039;saved.html&#039;, locals())قسمتی که نباید از دست داد این است که هنگام ایجاد یک ProfileForm یک تغییر ایجاد می شود، ما یک پارامتر دوم اضافه کردیم: request.FILES. در صورت عدم تصویب، اعتبار سنجی فرم با شکست مواجه می شود و پیامی می دهد که می گوید تصویر خالی است. اکنون، ما فقط به قالب saved.html و قالب profile.html برای فرم و صفحه تغییر مسیر نیاز داریم -myapp/templates/saved.html −&lt;html&gt;
   &lt;body&gt;
   
      {% if saved %}
         &lt;strong&gt;Your profile was saved.&lt;/strong&gt;
      {% endif %}
      
      {% if not saved %}
         &lt;strong&gt;Your profile was not saved.&lt;/strong&gt;
      {% endif %}
      
   &lt;/body&gt;
&lt;/html&gt;myapp/templates/profile.html −&lt;html&gt;
   &lt;body&gt;
   
      &lt;form name = &amp;quotform&amp;quot enctype = &amp;quotmultipart/form-data&amp;quot 
         action = &amp;quot{% url &amp;quotmyapp.views.SaveProfile&amp;quot %}&amp;quot method = &amp;quotPOST&amp;quot &gt;{% csrf_token %}
         
         &lt;div style = &amp;quotmax-width:470px;&amp;quot&gt;
            &lt;center&gt;  
               &lt;input type = &amp;quottext&amp;quot style = &amp;quotmargin-left:20%;&amp;quot 
               placeholder = &amp;quotName&amp;quot name = &amp;quotname&amp;quot /&gt;
            &lt;/center&gt;
         &lt;/div&gt;
			
         &lt;br&gt;
         
         &lt;div style = &amp;quotmax-width:470px;&amp;quot&gt;
            &lt;center&gt; 
               &lt;input type = &amp;quotfile&amp;quot style = &amp;quotmargin-left:20%;&amp;quot 
                  placeholder = &amp;quotPicture&amp;quot name = &amp;quotpicture&amp;quot /&gt;
            &lt;/center&gt;
         &lt;/div&gt;
			
         &lt;br&gt;
         
         &lt;div style = &amp;quotmax-width:470px;&amp;quot&gt;
            &lt;center&gt; 
            
               &lt;button style = &amp;quotborder:0px;background-color:#4285F4; margin-top:8%; 
                  height:35px; width:80%; margin-left:19%;&amp;quot type = &amp;quotsubmit&amp;quot value = &amp;quotLogin&amp;quot &gt;
                  &lt;strong&gt;Login&lt;/strong&gt;
               &lt;/button&gt;
               
            &lt;/center&gt;
         &lt;/div&gt;
         
      &lt;/form&gt;
      
   &lt;/body&gt;
&lt;/html&gt;در مرحله بعد، برای شروع به جفت URL های خود نیاز داریم: myapp/urls.pyfrom django.conf.urls import patterns, url
from django.views.generic import TemplateView

urlpatterns = patterns(
   &#039;myapp.views&#039;, url(r&#039;^profile/&#039;,TemplateView.as_view(
      template_name = &#039;profile.html&#039;)), url(r&#039;^saved/&#039;, &#039;SaveProfile&#039;, name = &#039;saved&#039;)
)When accessing &quot;/myapp/profile&quot;, we will get the following profile.html template rendered −And on form post, the saved template will be rendered −ما یک نمونه برای تصویر داریم، اما اگر می‌خواهید نوع دیگری از فایل را آپلود کنید، نه فقط تصویر، فقط ImageField را در Model و Form با FileField جایگزین کنید.Django - Apache Setupتا اینجا در مثال هایمان از وب سرور جنگو dev استفاده کرده ایم. اما این سرور فقط برای تست است و برای محیط تولید مناسب نیست. پس از تولید، به یک سرور واقعی مانند Apache، Nginx و غیره نیاز دارید. بیایید در این فصل به آپاچی بپردازیم. سرویس دهی برنامه های جنگو از طریق آپاچی با استفاده از mod_wsgi انجام می شود. بنابراین اولین چیز این است که مطمئن شوید Apache و mod_wsgi را نصب کرده اید. به یاد داشته باشید، زمانی که پروژه خود را ایجاد کردیم و به ساختار پروژه نگاه کردیم، به نظر می رسد -myproject/
   manage.py
   myproject/
      __init__.py
      settings.py
      urls.py
      wsgi.py
فایل wsgi.py فایلی است که از link بین جنگو و آپاچی مراقبت می کند. فرض کنید می خواهیم پروژه خود (myproject) را با آپاچی به اشتراک بگذاریم. فقط باید آپاچی را برای دسترسی به پوشه ما تنظیم کنیم. فرض کنید پوشه myproject خود را در حالت پیش فرض قرار داده ایم.همانطور که مشاهده می شود، آپاچی مسائل جنگو را مدیریت نمی کند. برای اینکه به این موضوع رسیدگی شود، باید آپاچی را در httpd.conf پیکربندی کنیم. بنابراین httpd.conf را باز کنید و خط زیر را اضافه کنید -WSGIScriptAlias / /var/www/html/myproject/myproject/wsgi.py
WSGIPythonPath /var/www/html/myproject/

&lt;Directory /var/www/html/myproject/&gt;
   &lt;Files wsgi.py&gt;
      Order deny,allow
      Allow from all
   &lt;/Files&gt;
&lt;/Directory&gt;اگر می توانید به صفحه ورود به سیستم به عنوان 127.0.0.1 دسترسی داشته باشیدDjango - Cookies Handlingگاهی اوقات ممکن است بخواهید برخی از داده ها را بر اساس هر بازدیدکننده سایت، مطابق با الزامات برنامه وب خود ذخیره کنید. همیشه به خاطر داشته باشید که کوکی‌ها در سمت سرویس گیرنده ذخیره می‌شوند و بسته به سطح امنیتی مرورگر مشتری شما، تنظیم کوکی‌ها گاهی می‌تواند کار کند و گاهی اوقات ممکن است نه. برای نشان دادن نحوه مدیریت کوکی ها در جنگو، بیایید یک سیستم با استفاده از سیستم ورود به سیستمی که قبلا ایجاد کردیم ایجاد کنیم. سیستم شما را به مدت X دقیقه وارد سیستم می‌کند و پس از آن زمان، از برنامه خارج خواهید شد. برای این کار باید دو کوکی، last_connection و username را تنظیم کنید. در ابتدا، اجازه دهید نمای ورود خود را برای ذخیره نام کاربری و کوکی‌های last_connection خود تغییر دهیمfrom django.template import RequestContext

def login(request):
   username = &amp;quotnot logged in&amp;quot
   
   if request.method == &amp;quotPOST&amp;quot:
      #Get the posted form
      MyLoginForm = LoginForm(request.POST)
   
   if MyLoginForm.is_valid():
      username = MyLoginForm.cleaned_data[&#039;username&#039;]
   else:
      MyLoginForm = LoginForm()
   
   response = render_to_response(request, &#039;loggedin.html&#039;, {&amp;quotusername&amp;quot : username}, 
      context_instance = RequestContext(request))
   
   response.set_cookie(&#039;last_connection&#039;, datetime.datetime.now())
   response.set_cookie(&#039;username&#039;, datetime.datetime.now())
	
   return response
همانطور که در نمای بالا مشاهده می شود، تنظیم کوکی با روش set_cookie انجام می شود که بر روی پاسخ فراخوانی می شود نه درخواست، و همچنین توجه داشته باشید که تمام مقادیر کوکی ها به عنوان رشته برگردانده می شوند. بیایید اکنون یک formView برای فرم ورود ایجاد کنیم، در صورتی که کوکی تنظیم شده باشد و از 10 ثانیه بیشتر نباشد، فرم را نمایش نخواهیم داد.def formView(request):
   if &#039;username&#039; in request.COOKIES and &#039;last_connection&#039; in request.COOKIES:
      username = request.COOKIES[&#039;username&#039;]
      
      last_connection = request.COOKIES[&#039;last_connection&#039;]
      last_connection_time = datetime.datetime.strptime(last_connection[:-7], 
         &amp;quot%Y-%m-%d %H:%M:%S&amp;quot)
      
      if (datetime.datetime.now() - last_connection_time).seconds &lt; 10:
         return render(request, &#039;loggedin.html&#039;, {&amp;quotusername&amp;quot : username})
      else:
         return render(request, &#039;login.html&#039;, {})
			
   else:
      return render(request, &#039;login.html&#039;, {})همانطور که در فرم مشاهده بالا مشاهده می کنید، دسترسی به کوکی که تنظیم کرده اید، از طریق ویژگی COOKIES (dict) درخواست انجام می شود. حالا بیایید فایل url.py را برای تغییر URL تغییر دهیم تا با نمای جدید ما جفت شودfrom django.conf.urls import patterns, url
from django.views.generic import TemplateView

urlpatterns = patterns(&#039;myapp.views&#039;,
   url(r&#039;^connection/&#039;,&#039;formView&#039;, name = &#039;loginform&#039;),
   url(r&#039;^login/&#039;, &#039;login&#039;, name = &#039;login&#039;))When accessing /myapp/connection, you will get the following page −و در ارسال − به صفحه زیر هدایت خواهید شداکنون، اگر سعی کنید دوباره در بازه 10 ثانیه ای به /myapp/connection دسترسی پیدا کنید، مستقیماً به صفحه دوم هدایت می شوید. و اگر دوباره خارج از این محدوده به /myapp/connection دسترسی پیدا کنید، فرم ورود به سیستم (صفحه 1) را دریافت خواهید کرد.Django - Sessionsهمانطور که قبلاً بحث شد، می‌توانیم از کوکی‌های سمت سرویس گیرنده برای ذخیره داده‌های مفید زیادی برای برنامه وب استفاده کنیم. قبلاً دیده‌ایم که می‌توانیم از کوکی‌های سمت کلاینت برای ذخیره داده‌های مختلف مفید برای برنامه وب خود استفاده کنیم. این به حفره های امنیتی زیادی بسته به اهمیت داده هایی که می خواهید ذخیره کنید منجر می شود. به دلایل امنیتی، جنگو یک چارچوب جلسه برای مدیریت کوکی ها دارد. از Session ها برای انتزاع دریافت و ارسال کوکی ها استفاده می شود، داده ها در سمت سرور ذخیره می شوند (مانند پایگاه داده)، و کوکی سمت سرویس گیرنده فقط یک شناسه جلسه برای شناسایی دارد. جلسات همچنین برای جلوگیری از مواردی که مرورگر کاربر روی «نپذیرفتن» کوکی‌ها تنظیم شده است مفید است.Setting Up Sessionsدر جنگو، فعال کردن جلسه در تنظیمات پروژه شما با افزودن چند خط به گزینه های MIDDLEWARE_CLASSES و INSTALLED_APPS انجام می شود. این باید در حین ایجاد پروژه انجام شود، اما دانستن آن همیشه خوب است، بنابراین MIDDLEWARE_CLASSES باید داشته باشد -&#039;django.contrib.sessions.middleware.SessionMiddleware&#039;And INSTALLED_APPS should have −&#039;django.contrib.sessions&#039;به طور پیش فرض، جنگو اطلاعات جلسه را در پایگاه داده (جدول یا مجموعه django_session) ذخیره می کند، اما می توانید موتور را برای ذخیره اطلاعات با استفاده از روش های دیگری مانند: در فایل یا در حافظه پنهان پیکربندی کنید. هنگامی که session فعال است، هر درخواست (اول آرگومان هر view در جنگو) دارای ویژگی session (dict) است. بیایید یک نمونه ساده ایجاد کنیم تا نحوه ایجاد و ذخیره جلسات را ببینیم. ما قبلاً یک سیستم ورود ساده ساخته‌ایم (به فصل پردازش فرم جنگو و فصل مدیریت کوکی‌های جنگو مراجعه کنید). اجازه دهید نام کاربری را در یک کوکی ذخیره کنیم تا در صورت عدم خروج از سیستم، هنگام دسترسی به صفحه ورود ما، فرم ورود را نبینید. اساساً، بیایید سیستم ورود خود را که در مدیریت کوکی‌های جنگو استفاده می‌کنیم، با ذخیره کوکی‌ها در سمت سرور، ایمن‌تر کنیم. برای این، ابتدا اجازه دهید نمای ورود خود را تغییر دهیم تا نام کاربری در سمت سرور کوکی ذخیره شود -def login(request):
   username = &#039;not logged in&#039;
   
   if request.method == &#039;POST&#039;:
      MyLoginForm = LoginForm(request.POST)
      
      if MyLoginForm.is_valid():
         username = MyLoginForm.cleaned_data[&#039;username&#039;]
         request.session[&#039;username&#039;] = username
      else:
         MyLoginForm = LoginForm()
			
   return render(request, &#039;loggedin.html&#039;, {&amp;quotusername&amp;quot : username}سپس اجازه دهید نمای formView را برای فرم ورود ایجاد کنیم، جایی که اگر کوکی تنظیم شده باشد، فرم را نمایش نمی دهیم -def formView(request):
   if request.session.has_key(&#039;username&#039;):
      username = request.session[&#039;username&#039;]
      return render(request, &#039;loggedin.html&#039;, {&amp;quotusername&amp;quot : username})
   else:
      return render(request, &#039;login.html&#039;, {})Now let us change the url.py file to change the url so it pairs with our new view −from django.conf.urls import patterns, url
from django.views.generic import TemplateView

urlpatterns = patterns(&#039;myapp.views&#039;,
   url(r&#039;^connection/&#039;,&#039;formView&#039;, name = &#039;loginform&#039;),
   url(r&#039;^login/&#039;, &#039;login&#039;, name = &#039;login&#039;))When accessing /myapp/connection, you will get to see the following page −And you will get redirected to the following page −حالا اگر دوباره سعی کنید به /myapp/connection دسترسی پیدا کنید، مستقیماً به صفحه دوم هدایت می شوید.Let&#x27;s create a simple logout view that erases our cookie.def logout(request):
   try:
      del request.session[&#039;username&#039;]
   except:
      pass
   return HttpResponse(&amp;quot&lt;strong&gt;You are logged out.&lt;/strong&gt;&amp;quot)And pair it with a logout URL in myapp/url.pyurl(r&#039;^logout/&#039;, &#039;logout&#039;, name = &#039;logout&#039;),Now, if you access /myapp/logout, you will get the following page −If you access /myapp/connection again, you will get the login form (screen 1).Some More Possible Actions Using Sessionsما نحوه ذخیره و دسترسی به یک جلسه را دیده‌ایم، اما خوب است بدانید که ویژگی session درخواست دارای اقدامات مفید دیگری مانند -set_expiry (value) − Sets the expiration time for the session.get_expiry_age() − Returns the number of seconds until this session expires.get_expiry_date() − Returns the date this session will expire.clear_expired() − Removes expired sessions from the session store.get_expire_at_browser_close() − Returns either True or False, depending on whether the user’s session cookies have expired when the user’s web browser is closed.Django - Cachingکش کردن چیزی به معنای ذخیره نتیجه یک محاسبه گران قیمت است، به طوری که دفعه بعد که به آن نیاز داشتید آن را انجام ندهید. در زیر یک شبه کد وجود دارد که نحوه عملکرد کش را توضیح می دهدgiven a URL, try finding that page in the cache

if the page is in the cache:
   return the cached page
else:
   generate the page
   save the generated page in the cache (for next time)
   return the generated pageجنگو دارای سیستم کش مخصوص به خود است که به شما امکان می دهد صفحات پویا خود را ذخیره کنید تا در صورت نیاز از محاسبه مجدد آنها جلوگیری کنید. نکته خوب در چارچوب جنگو کش این است که می توانید − را کش کنیدThe output of a specific view.A part of a template.Your entire site.برای استفاده از کش در جنگو، اولین کاری که باید انجام دهید این است که محل ماندن کش را تنظیم کنید. چارچوب کش امکانات مختلفی را ارائه می دهد - کش را می توان در پایگاه داده، در سیستم فایل یا مستقیماً در حافظه ذخیره کرد. تنظیمات در فایل settings.py پروژه شما انجام می شود.Setting Up Cache in DatabaseJust add the following in the project settings.py file −CACHES = {
   &#039;default&#039;: {
      &#039;BACKEND&#039;: &#039;django.core.cache.backends.db.DatabaseCache&#039;,
      &#039;LOCATION&#039;: &#039;my_table_name&#039;,
   }
}برای انجام این کار و تکمیل تنظیمات، باید جدول کش «my_table_name» را ایجاد کنیم. برای این کار، باید موارد زیر را انجام دهید -python manage.py createcachetableSetting Up Cache in File SystemJust add the following in the project settings.py file −CACHES = {
   &#039;default&#039;: {
      &#039;BACKEND&#039;: &#039;django.core.cache.backends.filebased.FileBasedCache&#039;,
      &#039;LOCATION&#039;: &#039;/var/tmp/django_cache&#039;,
   }
}Setting Up Cache in Memoryاین کارآمدترین روش کش است، برای استفاده از آن می‌توانید بسته به کتابخانه پایتونی که برای کش حافظه انتخاب می‌کنید از یکی از گزینه‌های زیر استفاده کنید.CACHES = {
   &#039;default&#039;: {
      &#039;BACKEND&#039;: &#039;django.core.cache.backends.memcached.MemcachedCache&#039;,
      &#039;LOCATION&#039;: &#039;127.0.0.1:11211&#039;,
   }
}OrCACHES = {
   &#039;default&#039;: {
      &#039;BACKEND&#039;: &#039;django.core.cache.backends.memcached.MemcachedCache&#039;,
      &#039;LOCATION&#039;: &#039;unix:/tmp/memcached.sock&#039;,
   }
}Caching the Entire Siteساده ترین راه استفاده از کش در جنگو، کش کردن کل سایت است. این کار با ویرایش گزینه MIDDLEWARE_CLASSES در تنظیمات پروژه انجام می شود. موارد زیر باید به گزینه - اضافه شودMIDDLEWARE_CLASSES += (
   &#039;django.middleware.cache.UpdateCacheMiddleware&#039;,
   &#039;django.middleware.common.CommonMiddleware&#039;,
   &#039;django.middleware.cache.FetchFromCacheMiddleware&#039;,
)توجه داشته باشید که ترتیب در اینجا مهم است، Update باید قبل از Fetch middleware باشد. سپس در همان فایل، باید − را تنظیم کنیدCACHE_MIDDLEWARE_ALIAS – The cache alias to use for storage.
CACHE_MIDDLEWARE_SECONDS – The number of seconds each page should be cached.Caching a Viewاگر نمی خواهید کل سایت را کش کنید، می توانید یک نمای خاص را کش کنید. این کار با استفاده از cache_page decorator همراه با جنگو انجام می شود. فرض کنید می‌خواهیم نتیجه نمای viewArticles − را کش کنیمfrom django.views.decorators.cache import cache_page

@cache_page(60 * 15)

def viewArticles(request, year, month):
   text = &amp;quotDisplaying articles of : %s/%s&amp;quot%(year, month)
   return HttpResponse(text)همانطور که می بینید cache_page به تعداد ثانیه هایی که می خواهید نتیجه view به عنوان پارامتر کش شود طول می کشد. در مثال بالا، نتیجه به مدت 15 دقیقه در حافظه پنهان ذخیره می شود. توجه - همانطور که قبلاً دیدیم نمای بالا به - نگاشت شده بودurlpatterns = patterns(&#039;myapp.views&#039;,
   url(r&#039;^articles/(?P&lt;month&gt;\d{2})/(?P&lt;year&gt;\d{4})/&#039;, &#039;viewArticles&#039;, name = &#039;articles&#039;),)از آنجایی که URL پارامترها را می گیرد، هر تماس مختلف به طور جداگانه ذخیره می شود. به عنوان مثال، درخواست بهurlpatterns = patterns(&#039;myapp.views&#039;,
   url(r&#039;^articles/(?P&lt;month&gt;\d{2})/(?P&lt;year&gt;\d{4})/&#039;, 
   cache_page(60 * 15)(&#039;viewArticles&#039;), name = &#039;articles&#039;),)و البته، دیگر در  myapp/views.py مورد نیاز نیستCaching a Template Fragmentشما همچنین می توانید بخش هایی از یک الگو را در حافظه پنهان نگه دارید، این کار با استفاده از تگ کش انجام می شود. بیایید الگوی hello.html خود را بگیریم -{% extends &amp;quotmain_template.html&amp;quot %}
{% block title %}My Hello Page{% endblock %}
{% block content %}

Hello World!!!&lt;p&gt;Today is {{today}}&lt;/p&gt;
We are
{% if today.day == 1 %}

the first day of month.
{% elif today == 30 %}

the last day of month.
{% else %}

I don&#039;t know.
{%endif%}

&lt;p&gt;
   {% for day in days_of_week %}
   {{day}}
&lt;/p&gt;

{% endfor %}
{% endblock %}و برای کش کردن بلوک محتوا، الگوی ما به − تبدیل می شود{% extends &amp;quotmain_template.html&amp;quot %}
{% block title %}My Hello Page{% endblock %}
{% block content %}

Hello World!!!&lt;p&gt;Today is {{today}}&lt;/p&gt;
We are
{% if today.day == 1 %}

the first day of month.
{% elif today == 30 %}

the last day of month.
{% else %}

I don&#039;t know.
{%endif%}

&lt;p&gt;
   {% for day in days_of_week %}
   {{day}}
&lt;/p&gt;

{% endfor %}
{% endblock %}And to cache the content block, our template will become −{% load cache %}
{% extends &amp;quotmain_template.html&amp;quot %}
{% block title %}My Hello Page{% endblock %}
{% cache 500 content %}
{% block content %}

Hello World!!!&lt;p&gt;Today is {{today}}&lt;/p&gt;
We are
{% if today.day == 1 %}

the first day of month.
{% elif today == 30 %}

the last day of month.
{% else %}

I don&#039;t know.
{%endif%}

&lt;p&gt;
   {% for day in days_of_week %}
   {{day}}
&lt;/p&gt;

{% endfor %}
{% endblock %}
{% endcache %}همانطور که در بالا می بینید، تگ کش 2 پارامتر می گیرد - زمانی که می خواهید بلوک کش شود (در ثانیه) و نامی که به قطعه کش داده شود.Django - Commentsقبل از شروع، توجه داشته باشید که چارچوب نظرات جنگو از نسخه 1.5 منسوخ شده است. اکنون می‌توانید از ویژگی خارجی برای این کار استفاده کنید، اما اگر همچنان می‌خواهید از آن استفاده کنید، همچنان در نسخه‌های 1.6 و 1.7 موجود است. شروع نسخه 1.8 وجود ندارد، اما همچنان می توانید کد را در یک حساب GitHub دیگر دریافت کنید. چارچوب نظرات، پیوست کردن نظرات را به هر مدلی در برنامه شما آسان می کند. برای شروع استفاده از چارچوب نظرات جنگو - فایل settings.py پروژه را ویرایش کنید و &quot;django.contrib.sites&quot; و &quot;django.contrib.comments&quot; را به گزینه INSTALLED_APPS اضافه کنید.INSTALLED_APPS += (&#039;django.contrib.sites&#039;, &#039;django.contrib.comments&#039;,)Get the site id −&gt;&gt;&gt; from django.contrib.sites.models import Site
&gt;&gt;&gt; Site().save()
&gt;&gt;&gt; Site.objects.all()[0].id
u&#039;56194498e13823167dd43c64Set the id you get in the settings.py file −SITE_ID = u&#039;56194498e13823167dd43c64&#039;همگام سازی db، برای ایجاد تمام جدول نظرات یا مجموعه -python manage.py syncdbAdd the comment app’s URLs to your project’s urls.py −from django.conf.urls import include
url(r&#039;^comments/&#039;, include(&#039;django.contrib.comments.urls&#039;)),اکنون که چارچوب را نصب کرده ایم، بیایید الگوهای hello خود را به ردیابی نظرات در مدل Dreamreal خود تغییر دهیم. ما نظرات را برای یک ورودی Dreamreal خاص لیست می کنیم و ذخیره می کنیم که نام آن به عنوان پارامتر به آن ارسال می شودDreamreal Modelclass Dreamreal(models.Model):

   website = models.CharField(max_length = 50)
   mail = models.CharField(max_length = 50)
   name = models.CharField(max_length = 50)
   phonenumber = models.IntegerField()

   class Meta:
      db_table = &amp;quotdreamreal&amp;quothello viewdef hello(request, Name):
   today = datetime.datetime.now().date()
   daysOfWeek = [&#039;Mon&#039;, &#039;Tue&#039;, &#039;Wed&#039;, &#039;Thu&#039;, &#039;Fri&#039;, &#039;Sat&#039;, &#039;Sun&#039;]
   dreamreal = Dreamreal.objects.get(name = Name)
   return render(request, &#039;hello.html&#039;, locals())hello.html template{% extends &amp;quotmain_template.html&amp;quot %}
{% load comments %}
{% block title %}My Hello Page{% endblock %}
{% block content %}

&lt;p&gt;
   Our Dreamreal Entry:
   &lt;p&gt;&lt;strong&gt;Name :&lt;/strong&gt; {{dreamreal.name}}&lt;/p&gt;
   &lt;p&gt;&lt;strong&gt;Website :&lt;/strong&gt; {{dreamreal.website}}&lt;/p&gt;
   &lt;p&gt;&lt;strong&gt;Phone :&lt;/strong&gt; {{dreamreal.phonenumber}}&lt;/p&gt;
   &lt;p&gt;&lt;strong&gt;Number of comments :&lt;strong&gt; 
   {% get_comment_count for dreamreal as comment_count %} {{ comment_count }}&lt;/p&gt;
   &lt;p&gt;List of comments :&lt;/p&gt;
   {% render_comment_list for dreamreal %}
&lt;/p&gt;

{% render_comment_form for dreamreal %}
{% endblock %}Finally the mapping URL to our hello view −url(r&#039;^hello/(?P&lt;Name&gt;\w+)/&#039;, &#039;hello&#039;, name = &#039;hello&#039;),Now,در قالب ما (hello.html)، چارچوب نظرات را با − {% load comments %} بارگیری کنید.ما تعداد نظرات مربوط به شی Dreamreal را از نمای مشاهده می کنیم - {% get_comment_count برای dreamreal به عنوان comment_count %}ما لیست نظرات اشیاء را دریافت می کنیم - {% render_comment_list for dreamreal %}ما فرم نظرات پیش فرض را نمایش می دهیم - {% render_comment_form for dreamreal %}هنگام دسترسی به /myapp/hello/steve، اطلاعات نظرات مربوط به مدخل Dreamreal که نام آن استیو است را دریافت خواهید کرد. دسترسی به آن URL شما را دریافت می کند -On posting a comment, you will get redirected to the following page −If you go to /myapp/hello/steve again, you will get to see the following page −همانطور که می بینید، تعداد نظرات در حال حاضر 1 است و شما نظر را در زیر خط لیست نظرات دارید.Django - RSSجنگو با یک چارچوب تولید خوراک سندیکایی عرضه می شود. با آن می‌توانید فیدهای RSS یا Atom را فقط با زیر کلاس‌بندی کلاس django.contrib.syndication.views.Feed ایجاد کنید.بیایید یک فید برای آخرین نظرات انجام شده در برنامه ایجاد کنیم (همچنین به فصل جنگو - چارچوب نظرات مراجعه کنید)برای این، بیایید یک myapp/feeds.py ایجاد کنیم و فید خود را تعریف کنیم (شما می توانید کلاس های فید خود را در هر جایی که می خواهید در ساختار کد خود قرار دهید).from django.contrib.syndication.views import Feed
from django.contrib.comments import Comment
from django.core.urlresolvers import reverse

class DreamrealCommentsFeed(Feed):
   title = &amp;quotDreamreal&#039;s comments&amp;quot
   link = &amp;quot/drcomments/&amp;quot
   description = &amp;quotUpdates on new comments on Dreamreal entry.&amp;quot

   def items(self):
      return Comment.objects.all().order_by(&amp;quot-submit_date&amp;quot)[:5]
		
   def item_title(self, item):
      return item.user_name
		
   def item_description(self, item):
      return item.comment
		
   def item_link(self, item):
      return reverse(&#039;comment&#039;, kwargs = {&#039;object_pk&#039;:item.pk})در کلاس فید ما، ویژگی‌های عنوان، پیوند و توضیحات با عناصر استاندارد &lt;title&gt;، &lt;link&gt; و &lt;description&gt; RSS مطابقت دارند.روش آیتم ها، عناصری را که باید در فید به عنوان عنصر آیتم وارد شوند، برمی گرداند. در مورد ما پنج نظر آخر.روش item_title، چیزی را به عنوان عنوان مورد فید ما دریافت می کند. در مورد ما عنوان، نام کاربری خواهد بود.روش item_description، آنچه را که به عنوان توضیحات برای مورد فید ما خواهد بود، دریافت می کند. در مورد ما خود نظر.متد item_link پیوند را به آیتم کامل می‌سازد. در مورد ما، شما را به نظر می رساند.اکنون که فید خود را داریم، بیایید یک نمای نظر در views.py اضافه کنیم تا نظر خود را نمایش دهیم -from django.contrib.comments import Comment

def comment(request, object_pk):
   mycomment = Comment.objects.get(object_pk = object_pk)
   text = &#039;&lt;strong&gt;User :&lt;/strong&gt; %s &lt;p&gt;&#039;%mycomment.user_name&lt;/p&gt;
   text += &#039;&lt;strong&gt;Comment :&lt;/strong&gt; %s &lt;p&gt;&#039;%mycomment.comment&lt;/p&gt;
   return HttpResponse(text)We also need some URLs in our myapp urls.py for mapping −from myapp.feeds import DreamrealCommentsFeed
from django.conf.urls import patterns, url

urlpatterns += patterns(&#039;&#039;,
   url(r&#039;^latest/comments/&#039;, DreamrealCommentsFeed()),
   url(r&#039;^comment/(?P\w+)/&#039;, &#039;comment&#039;, name = &#039;comment&#039;),
)When accessing /myapp/latest/comments/ you will get our feed −سپس با کلیک بر روی یکی از نام‌های کاربری به موارد زیر هدایت می‌شوید:بنابراین، تعریف یک فید RSS فقط یک موضوع زیر طبقه بندی کلاس Feed و اطمینان از تعریف URL ها (یکی برای دسترسی به فید و دیگری برای دسترسی به عناصر فید) است. درست به عنوان نظر، این می تواند به هر مدلی در برنامه شما متصل شود.Django - AjaxAjax اساساً ترکیبی از فناوری‌هایی است که برای کاهش تعداد بارگذاری صفحات با یکدیگر یکپارچه شده‌اند. ما معمولاً از Ajax برای سهولت تجربه کاربر نهایی استفاده می کنیم. استفاده از Ajax در Django را می توان با استفاده مستقیم از یک کتابخانه Ajax مانند JQuery یا موارد دیگر انجام داد. فرض کنید می خواهید از JQuery استفاده کنید، سپس باید کتابخانه را از طریق آپاچی یا سایرین روی سرور خود دانلود و سرویس کنید. سپس از آن در قالب خود استفاده کنید، درست مانند کاری که ممکن است هنگام توسعه هر برنامه مبتنی بر Ajax انجام دهید. راه دیگر استفاده از Ajax در جنگو استفاده از فریمورک Django Ajax است. رایج ترین مورد استفاده، django-dajax است که ابزاری قدرتمند برای توسعه آسان و فوق العاده سریع منطق ارائه ناهمزمان در برنامه های وب، با استفاده از پایتون و تقریباً بدون کد منبع جاوا اسکریپت است. چهار مورد از محبوب ترین فریم ورک های آژاکس را پشتیبانی می کند: Prototype، jQuery، Dojo و MooTools.Using Django-dajaxاولین کاری که باید انجام دهید این است که django-dajax را نصب کنید. این را می توان با استفاده از easy_install یا pip − انجام داد$ pip install django_dajax
$ easy_install django_dajaxاین به طور خودکار django-dajaxice مورد نیاز django-dajax را نصب می کند. سپس باید هم dajax و هم dajaxice را پیکربندی کنیم. dajax و dajaxice را در تنظیمات پروژه خود در گزینه INSTALLED_APPS اضافه کنیدINSTALLED_APPS += (
   &#039;dajaxice&#039;,
   &#039;dajax&#039;
)Make sure in the same settings.py file, you have the following −TEMPLATE_LOADERS = (
   &#039;django.template.loaders.filesystem.Loader&#039;,
   &#039;django.template.loaders.app_directories.Loader&#039;,
   &#039;django.template.loaders.eggs.Loader&#039;,
)

TEMPLATE_CONTEXT_PROCESSORS = (
   &#039;django.contrib.auth.context_processors.auth&#039;,
   &#039;django.core.context_processors.debug&#039;,
   &#039;django.core.context_processors.i18n&#039;,
   &#039;django.core.context_processors.media&#039;,
   &#039;django.core.context_processors.static&#039;,
   &#039;django.core.context_processors.request&#039;,
   &#039;django.contrib.messages.context_processors.messages&#039;
)

STATICFILES_FINDERS = (
   &#039;django.contrib.staticfiles.finders.FileSystemFinder&#039;,
   &#039;django.contrib.staticfiles.finders.AppDirectoriesFinder&#039;,
   &#039;dajaxice.finders.DajaxiceFinder&#039;,
)

DAJAXICE_MEDIA_PREFIX = &#039;dajaxice&#039;Now go to the myapp/url.py file and make sure you have the following to set dajax URLs and to load dajax statics js files −from dajaxice.core import dajaxice_autodiscover, dajaxice_config
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.conf import settings

Then dajax urls:

urlpatterns += patterns(&#039;&#039;,
   url(r&#039;^%s/&#039; % settings.DAJAXICE_MEDIA_PREFIX, include(&#039;dajaxice.urls&#039;)),)
	
urlpatterns += staticfiles_urlpatterns()Let us create a simple form based on our Dreamreal model to store it, using Ajax (means no refresh).At first, we need our Dreamreal form in myapp/form.py.class DreamrealForm(forms.Form):
   website = forms.CharField(max_length = 100)
   name = forms.CharField(max_length = 100)
   phonenumber = forms.CharField(max_length = 50)
   email = forms.CharField(max_length = 100)Then we need an ajax.py file in our application: myapp/ajax.py. That&#x27;s where is our logic, that&#x27;s where we put the function that will be saving our form then return the popup −from dajaxice.utils import deserialize_form
from myapp.form import DreamrealForm
from dajax.core import Dajax
from myapp.models import Dreamreal

@dajaxice_register
def send_form(request, form):
   dajax = Dajax()
   form = DreamrealForm(deserialize_form(form))
   
   if form.is_valid():
      dajax.remove_css_class(&#039;#my_form input&#039;, &#039;error&#039;)
      dr = Dreamreal()
      dr.website = form.cleaned_data.get(&#039;website&#039;)
      dr.name = form.cleaned_data.get(&#039;name&#039;)
      dr.phonenumber = form.cleaned_data.get(&#039;phonenumber&#039;)
      dr.save()
      
      dajax.alert&#40;&amp;quotDreamreal Entry %s was successfully saved.&amp;quot % 
         form.cleaned_data.get(&#039;name&#039;&#41;)
   else:
      dajax.remove_css_class(&#039;#my_form input&#039;, &#039;error&#039;)
      for error in form.errors:
         dajax.add_css_class(&#039;#id_%s&#039; % error, &#039;error&#039;)
			
   return dajax.json()Now let&#x27;s create the dreamreal.html template, which has our form −&lt;html&gt;
   &lt;head&gt;&lt;/head&gt;
   &lt;body&gt;
   
      &lt;form action = &amp;quot&amp;quot method = &amp;quotpost&amp;quot id = &amp;quotmy_form&amp;quot accept-charset = &amp;quotutf-8&amp;quot&gt;
         {{ form.as_p }}
         &lt;p&gt;&lt;input type = &amp;quotbutton&amp;quot value = &amp;quotSend&amp;quot  = &amp;quotsend_form();&amp;quot&gt;&lt;/p&gt;
      &lt;/form&gt;
      
   &lt;/body&gt;
&lt;/html&gt;Add the view that goes with the template in myapp/views.py −def dreamreal(request):
   form = DreamrealForm()
   return render(request, &#039;dreamreal.html&#039;, locals())Add the corresponding URL in myapp/urls.py −url(r&#039;^dreamreal/&#039;, &#039;dreamreal&#039;, name = &#039;dreamreal&#039;),Now let&#x27;s add the necessary in our template to make the Ajax work −At the top of the file add −{% load static %}
{% load dajaxice_templatetags %}And in the &lt;head&gt; section of our dreamreal.html template add −We are using the JQuery library for this example, so add −&lt;script src = &amp;quot{% static &#039;/static/jquery-1.11.3.min.js&#039; %}&amp;quot 
   type = &amp;quottext/javascript&amp;quot charset = &amp;quotutf-8&amp;quot&gt;
&lt;script src = &amp;quot{% static &#039;/static/dajax/jquery.dajax.core.js&#039; %}&amp;quot&gt;The Ajax function that will be called on click −

   function send_form(){
      Dajaxice.myapp.send_form(Dajax.process,{&#039;form&#039;:$(&#039;#my_form&#039;).serialize(true)});
   }
Note that you need the “jquery-1.11.3.min.js” in your static files directory, and also the jquery.dajax.core.js. To make sure all dajax static files are served under your static directory, run −$python manage.py collectstaticNote − Sometimes the jquery.dajax.core.js can be missing, if that happens, just download the source and take that file and put it under your static folder.You will get to see the following screen, upon accessing /myapp/dreamreal/ −On submit, you will get the following screen −</description>
                <category>جواد جهانگیری</category>
                <author>جواد جهانگیری</author>
                <pubDate>Wed, 16 Feb 2022 10:46:50 +0330</pubDate>
            </item>
                    <item>
                <title>آموزش نحوه استفاده از Redis Desktop Manager</title>
                <link>https://virgool.io/@javadjahangiri/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%D9%86%D8%AD%D9%88%D9%87-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-redis-desktop-manager-%D8%A8%D9%87%D8%AA%D8%B1%DB%8C%D9%86-%D8%A7%D8%A8%D8%B2%D8%A7%D8%B1-%DA%AF%D8%B1%D8%A7%D9%81%DB%8C%DA%A9%DB%8C-%D8%A8%D8%B1%D8%A7%DB%8C-%DA%A9%D8%A7%D8%B1-%D8%A8%D8%A7-%D8%AF%DB%8C%D8%AA%D8%A7%D8%A8%DB%8C%D8%B3-redis-g6f6ccrktd19</link>
                <description>به نام آن که جان را فکرت آموخت / چراغ دل به نور جان برافروختبا عرض سلام و وقت بخیر خدمت کاربران محترم سایت ویرگول، در این مقاله آموزشی درباره نحوه کار کردن با RDM (Redis Desktop Manager) که یکی از بهترین ابزارهای گرافیکی برای کار کردن با Redis می باشد و سعی شده یک آموزش کاربردی و پروژه محور برای کار با دیتابیس Redis توسط ابزار RDM ارایه گردد.ایده این سری مقاله های آموزشی از این موضوع سرچشمه می گیرد که بخشی از خوانندگان وجود دارد که به محتوای نوشتاری آنلاین بهتر پاسخ می دهند و ترجیج می دهند مهارت های جدید را به سرعت از طریق خواندن افزایش دهند.این سری اموزش ها با ارایه اولین پکیج آموزشی در خصوص Redis آغاز می شود که انتظار می رود با واکنش مثبت کاربران همراه شود.توجه: این مقاله به مرور زمان، ویرایش و یا تکمیل می‌شود!تقاضا: در صورتی که با مشکل تایپی، دستوری و یا مفهومی در این مقاله برخورد کردید، از شما دوست عزیز و گرامی، صمیمانه تقاضا می‌کنم که اینجانب را مطلع کرده، تا نسبت به تصحیح و یا تکمیل آن، در اسرع وقت، اقدام نمایم.با کمال تشکر جواد جهانگیریشماره تلفن همراه: 09149431772نشانی پست الکترونیکی: javad.jahangiri.niopdc@gmail.comفیلم‌های آموزشی در آپارات:جواد جهانگیری (CTO) - آپاراتفیلم آموزشی در یوتویب: javad jahangiri - YouTubeنسخه مقاله: 1.1- تاریخ بروزرسانی: 1400/10/03 https://www.aparat.com/javadjahangiriniopdc/playlists  https://www.aparat.com/javadjahangiriniopdc/playlists What is Redis Desktop ManagerGUI Client for redisیک برنامه گرافیکی برای کار کردن با دیتابیس ردیس می باشد که می توانیم از طریق محیط گرافیکی با دیتابیس ردیس تعامل داشته باشیمOpen Source | Cross Platformیک برنامه اوپن سورس و کراس پلتفرم می باشد که قابلیت استفاده در ویندوز ,لینوکس و مک را داردHow to use Redis desktop managerوارد گیت هاب Redis desktop manager می شویم https://github.com/uglide/RedisDesktopManager از پایین صفحه نسبت به دانلود نسخه رایگان RDM اقدام می کنیمتوجه داشته باشید با یک جستجوی ساده redis desktop manager free download در سطح google از سایت های مختلف می توانید بصورت رایگان این نرم افزار را نیز دانلود کنیدهمچنین از طریق لینک زیر می توانید به مستندات اموزشی این ابزار بر روی گیت دسترسی داشته باشید https://docs.rdm.dev/en/latest/ نحوه نصب RDM (redis desktop manager)مراحل نصب را به شرح ذیل پیش می رویمنحوه اتصالRDM (redis desktop manager) به دیتابیس Redisپیشنهاد می شود حتما قبل از مطالعه این آموزش مقاله آموزش دیتابیس ردیس Redis Tutorial از لینک زیر مطالعه شودتا با نحوه نصب و راه اندازی دیتابیس Redis و دستورات ان آشنا شوید  https://vrgl.ir/kxO2U حال که دیتابیس ردیس را با یکی از سه روش یاد شده در مقاله فوق راه اندازی کردید نوبت به اتصال برنامه RDMبه دیتابیس Redis می رسداین مقاله اموزش هنوز تمام نشده است و درحین تهیه می باشد !!!با تشکر از مطالعه این مقاله، مثل همیشه کنجکاو باشید!!!در دوره های آموزش آنلاین تضمینی مجتمع فنی ارومیه که به صورت خصوصی و عمومی در دو شیوه حضوری و آنلاین برگزار می شود سرفصل های بسیار متنوع و کاربردی را بصورت پروژه محور آموزش داده می شود تا شخص کارآموز بتواند بلافاصله پس از اتمام این دوره در کمترین زمان ممکن وارد بازار کار شود.آموزش تخصص ماست با ما حرفه ای شویدجهت مشاوره با شماره 09149431772 در ارتباط باشید ... https://www.aparat.com/javadjahangiriniopdc/playlists </description>
                <category>جواد جهانگیری</category>
                <author>جواد جهانگیری</author>
                <pubDate>Fri, 24 Dec 2021 10:31:08 +0330</pubDate>
            </item>
                    <item>
                <title>نکات کاربردی داکر (docker) برای برنامه نویسان دات نت (Net.) و مدیریت بانک های اطلاعاتی SQLSERVER</title>
                <link>https://virgool.io/@javadjahangiri/%D9%86%DA%A9%D8%A7%D8%AA-%DA%A9%D8%A7%D8%B1%D8%A8%D8%B1%D8%AF%DB%8C-%D8%AF%D8%A7%DA%A9%D8%B1-docker-%D8%A8%D8%B1%D8%A7%DB%8C-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%D8%A7%D9%86-%D8%AF%D8%A7%D8%AA-%D9%86%D8%AA-net-%D9%88-%D9%85%D8%AF%DB%8C%D8%B1%DB%8C%D8%AA-%D8%A8%D8%A7%D9%86%DA%A9-%D9%87%D8%A7%DB%8C-%D8%A7%D8%B7%D9%84%D8%A7%D8%B9%D8%A7%D8%AA%DB%8C-sqlserver-jtni7q8girzd</link>
                <description>به نام آن که جان را فکرت آموخت / چراغ دل به نور جان برافروختبا سلام و تشکر از مطالعه مقالات بنده در کانال ویرگول ،  این مقاله شامل نکات کاربردی داکر برای برنامه نویسان دانت و مدیریت بانک های اطلاعاتی SQLSERVER در داکر می باشد .هدف از این مقاله اموزش داکر نمی باشد زیرا آموزش کامل و مفیدی در راستای داکر در سطح اینترنت به زبان انگلیسی و هم به زبان فارسی وجود دارد که در طی مقاله چندین منبع خوب اموزشی داکر به زبان فارسی معرفی می شود که بعنوان پیشنیاز این مقاله مطالعه شود در ابتدا نحوه نصب و راه اندازی  SQLSERVER2019  بر روی داکر  و کار با  این بانک اطلاعاتی بر روی داکر بررسی می شود و سپس دستورات کاربردی داکر برای برنامه نویسان دانت کور بررسی می شود و در نهایت نحوه داکرایز کردن یک پروژه دانت کوری بررسی می شود.ایده این سری مقاله های آموزشی از این موضوع سرچشمه می گیرد که بخشی از خوانندگان وجود دارد که به محتوای نوشتاری آنلاین بهتر پاسخ می دهند و ترجیج می دهند مهارت های جدید را به سرعت از طریق خواندن افزایش دهند.این سری اموزش ها با ارایه پکیج آموزش های کاربردی در خصوص C# asp.net core آغاز می شود که انتظار می رود با واکنش مثبت کاربران همراه شود.توجه: این مقاله به مرور زمان، ویرایش و یا تکمیل می‌شود!تقاضا: در صورتی که با مشکل تایپی، دستوری و یا مفهومی در این مقاله برخورد کردید، از شما دوست عزیز و گرامی، صمیمانه تقاضا می‌کنم که اینجانب را مطلع کرده، تا نسبت به تصحیح و یا تکمیل آن، در اسرع وقت، اقدام نمایم.با کمال تشکرجواد جهانگیریشماره تلفن همراه: 09149431772نشانی پست الکترونیکی: javad.jahangiri.niopdc@gmail.comفیلم‌های آموزشی در آپارات:جواد جهانگیری (CTO) - آپاراتفیلم آموزشی در یوتویب: javad jahangiri - YouTubeنسخه مقاله: ۱.۱ - تاریخ بروزرسانی: 1400/09/27 با عنایت به اینکه در سط اینترنت مقالات و اموزش های خوبی برای داکر موجود است هدف از این مقاله به هیچ عنوان اموزش داکر نیست  با عنایت به اینکه بنده یک متخصص داکر نیستم ولی بعنوان یک برنامه نویس که از داکر استفاده می کنیم نکات کاربردی برای شما ارایه می شود همانطور که اشاره شد یکسری سایت اموزشی مفید برای مطالعه داکر معرفی خواهد شد یکی از بهترین منابع آموزشی داکر به انگلیسی خود مستندات سایت داکر می باشد: https://docs.docker.com/get-started/ در سایت های فارسی هم نظر شخصی بنده سایت داکرمی دارای مقالات و اموزش های کاملی برای داکر هست: https://dockerme.ir/ منبع آموزشی برای مقاله جاری مثل همیشه خود سایت مایکروسافت می باشد: https://docs.docker.com/samples/dotnetcore/  https://docs.microsoft.com/en-us/sql/linux/quickstart-install-connect-docker?view=sql-server-ver15&amp;pivots=cs1-bash می باشد بریم که اموزش را شروع کنیم:تفاوت داکر با ماشین مجازی ؛ داکر چیست ؟همانطوی که در شکل بالا مشاهده می کنید در مجازی سازی ما یک سخت افزاری داریم که بر روی ان یک Hypervisor (مثل VMware ، Hyper-V،KVM) وجود دارد که برای شبیه سازی سخت افزار برای ماشین های مجازی  که در سطح بالاتر ان قرار می گیرد استفاده می شود. مجازی سازی مزایای خیلی زیاد دارد و بصورت گسترده در اتاق سرورها و دیتاسنتر ها استفاده می شود یکی از مهمترین مزیت های ان این است که سیستم عامل بصورت کاملا جدا از هم کار می کنددر داکر ما بر روی HOST OS یک لایه نازک بنام Docker Engine داریم که روی ان کانتنر های ما سوار می شود فرق کانتینر با ماشین مجازی این است که ماشین مجازی یک سیستم عامل کامل با کرنل مستقل می باشد ولی کانتینر کرنل مستقل ندارد و خیلی از نیازهای خود را می تواند از HOST OS قرض بگیرند و موتور داکر وقت چیزهای که لازم دارید در کانتینر بالا می اورد لذا کانتینر های سبک و کوچیک هستند در مجازی سازی به روش مجازی خود Hypervisor یک سربار زیادی برای ما ایجاد می کند و همچنین مجبور هستیم یک سیستم عامل کامل را بالا بیاوریم ولی در کانتینر فقط چیزهای که لازم دارد از سیستم عامل هاست درخواست می کند لذا می توانیم کانتینر داشته باشیم با سایز فقط 2k بایت بنام Hello Word ،زیرا فقط چیزی که لازم دارد از هاست اوس ما درخواست می کند برای مثال اگر کرنل لازم دارد و یا حافظه ای برای اجرا لازم دارد از سیستم عامل هاست درخواست میکند ولی ایزوله بودن ان نسبت به VM کمتر هست در ماشین های مجازی بحث ایزوله بودن بیشتر می باشد(دوستان که به مباحث امنیت اطلاعات علاقه مند هستند روش های برای  رد کردن این ایزولاسیون  وجود دارد ?) در داکر پیچیدگی کمتر هست و Scalable (مقیاس پذیر ) می باشد فرض کنید ما یک کانتینر داریم که یک دتیابیس هستش و یک کانتینر دیگر داریم که یه برنامه می باشد که به مشتریان سرویس می دهد حالا فرض کنید تعداد درخواست ها بالا می رود و یک App ما جواب نمی دهد براحتی می توانیم یک APP دیگر بالا بیاوریم و مقیاس پذیری در داکر خیلی بالا می باشددر مورد مزایای دیگر داکر فرض کنید ما یک برنامه داریم که نیاز به یکسری پیش نیازهای نصب و راه اندازی دارد اگر این برنامه را به کسی بدهیم باید بهش یه راهنما هم بدهیم که این پیش نیاز ها رو سیستم عامل خودت نصب کن بعد برنامه ما کار می کند ولی در داکر این کار براحتی انجام می شود یک docfile به مشتری می دهیم و یا یک Image داکری برای ان می سازیم بهش می دهیم و مشتری می  تواند با این داکر فایل براحتی برنامه ما را بالا بیاورد و یا فرض کنید برنامه ما باید تو یک سرور راه اندازی شود مسئول ان شبکه باید یکسری پیش نیاز های ما روی سرور نصب کند با فرض این پکیجی روی ان سرور باشد که با پکیج های ما سازگاری نداشته باشد در این حالت خیلی مشکلات بوجود می اید ولی در داکر با دادن این داکر فایل مشکل براحتی حل می شود مسئول شبکه با داکر فایل ما یک ایمیج داکر می سازد و از روی ان کانتینر ان را بالامی اورد و برنامه ما براحتی بر روی سرور بالا می اید دقت کنید در حالت حتی ما پلتفرم خاصی نیاز داریم که سیستم عامل سرور ما لینوکس باشد یا ویندوز و … ما چون در این مقاله قصد اموزش کامل داکر را نداریم با فرض اینکه داکر را می خواهیم روی ویندوز نصب کنیم برای اینکه نسخه جدید داکر در ویندوز با WSL2 سازگار می باشد و توصیه می شود با توزیع Ubuntu نیز  integration شود ابتدا مطابق مراحل زیر پیش نیاز های نصب داکر را در ویندوز بصورت کاربردی و سریع طی می کنیم:تکنولوژی (WSL) چیست؟این تکنولوژی مخفف Windows Subsystem for Linux می باشد و راهی برای اجرای لینوکس (هسته لینوکس واقعی) بر روی ویندوز است که تقریبا از تمامی توزیع های لینوکس پشتیبانی می کنهتفاوت بین ماشین های مجازی و WSL چیست؟تفاوت اصلی این است که ویندوز تماس های سیستم WSL را به دستورالعمل های بومی ویندوز ترجمه می کند ، این بدان معناست که شبیه لینوکس اصلی است و لی ماشین های مجازی تماس های سیستم را شبیه سازی می کند.از روی راهنمایی زیر در سایت مایکروسافت WSL را نصب کنید حتما به نسخه WLS2  بروزرسانی کنید نکته : دقت شود حتما نسخه wsl رو نسخه دو تنظیم شود:wsl --set-default-version 2که با یک سرچ ساده در اینترنت می توانید ان را نصب کنید و در سایت خود مایکروسافت هم مرحله به مرحله مراحل نصب وجود دارد. https://docs.microsoft.com/en-us/windows/wsl/install توجه شود که WSL2 اجازه اجرای نسخه های مختلف لینوکس در ویندوز می دهد با توجه به اینکه ابونتو محبوب تر می باشد پس پیشنهاد و توصیه می شود که Ubuntu در WSL2 نصب کنیدمطابق مقاله زیر می توانید اوبونتو را در WSL2 نصب کنید: https://altis.com.au/installing-ubuntu-bash-for-windows-10-wsl2-setup/ توجه شود حتما توزیع ابونتو لینوکس بعنوان engine مربوط به wsl تنظیم شودwsl --list --verbose
wsl --set-default ubuntuWindows Terminalدر مرحله بعد پیشنهاد می شود و توصیه می شود که Windows Terminal را بروی ویندوزتان نصب کنید https://docs.microsoft.com/en-us/windows/terminal/install در نهایت می بایستی ترمینال جدید ویندوز به شرح زیر باز می شودبعد از نصب پیش نیازها نسبت به نصب Docker Desktop از لینک زیر اقدام شود https://www.docker.com/products/docker-desktop دقت شود بعد از نصب داکر دسکتاپ می بایستی مطابق شکل زیر  از قسمت تنظیمات به منوی Resource وارد می شویم و گزینه Enable integration with my default wsl distor می بایستی فعال بود و همچنین گزینه  Enable integration with additional distro برای Ubuntu فعال کنیددستورات کاربردی داکرنحوه نمایش ایمیج های داکرdocker imagesنحوه نمایش کانتینرهای در حین اجراdocker psنحوه نمایش  همه کانتینرها (چه انهای که در گذشته اجراشده و چه انهای که در حین اجرا می باشد)docker ps -aنحوه پاک کردن یک کانتینرdocker rm container-idنحوه پاک کردن تمامی کانتینرهاdocker container pruneنحوه پاک کردن ایمیج داکرdocker rmi image-name
                   i for remove imageنحوه اجرا کردن یک داکر docker run name-dockerنحوه اجرا کردن یک داکر بصورت اینتراکتیوdocker run -it docker-image  نحوه اجرا کردن یک داکر بصورت اینتراکتیو و پاک شدن کانتینر بعد از خروج از داکرdocker rum --rm -it docker-image             
     --rm for remove container on close 
     --it interactive and tty for input and output in dockerنحوه اجرا کردن یک دستور در داخل یک کانتینر داکرUsage:  docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
Run a command in a running container
Options:
  -d, --detach               Detached mode: run command in the background
      --detach-keys string   Override the key sequence for detaching a container
  -e, --env list             Set environment variables
      --env-file list        Read in a file of environment variables
  -i, --interactive          Keep STDIN open even if not attached
      --privileged           Give extended privileges to the command
  -t, --tty                  Allocate a pseudo-TTY
  -u, --user string          Username or UID (format: &lt;name|uid&gt;[:&lt;group|gid&gt;])
  -w, --workdir string       Working directory inside the containerمثال :نحوه اجرای  bash در داخل یک کانتینر:docker exec -it contianer bashPublish  port (-p)docker run -p hostip:hostport:contianerport/tcp containername
docker run -p 127.0.0.1:80:8080/tcp ubuntu  
docker run -p 80:8080/tcp ubuntu
docker run -p 80:8080 ubuntuاین پورت 8080 کانتینر را به پورت TCP 80 در 127.0.0.1 دستگاه میزبان متصل می کند. همچنین می توانید پورت های udp و sctp را مشخص کنید. توجه کنید در صورتی که مقدار hostip نوشته نشود مقدار پیش فرض ان 127.0.0.1 می باشد اگر پروتکل مشخص نشود مقدار ان tcp می باشددرحقیقت هاست پورت همان پورت خارجی می باشد که ما را به کانتینر پورت داخلی این کانتینر وصل می کندdocker run -p 6379:6379 redisاین دستور پورت 6379 هاست ما (دنیای خارجی ) را به پورت 6379 داخلی ردیس که روی ان بصورت پیش فرض سرویس می دهد متصل می کنیدنحوه save کردن ایمیج داکر(پشتیبان گیری از ایمیج ها داکر)همانگونه که مستحضرید ما توسط داکر هاب تحریم شدیم درست است می توانیم از طریق سایت شکن این تحریم ها را دور زد https://shecan.ir/ ولی سرعت دانلود ایمیج ها برای ما کند می باشد و درصورت نیاز لازم دارید که این ایمیج ها پشتیبان گیری کنید و یا بصورت فنی تر ان ها را save کنید که در صورت نیاز در اینده ان ها به جای دانلود براحتی ان ها را از روی هارد خودتان  load  کنیدdocker saveDescriptionSave one or more images to a tar archive (streamed to STDOUT by default)Usage$ docker save [OPTIONS] IMAGE [IMAGE...]Extended descriptionProduces a tarred repository to the standard output stream. Contains all parent layers, and all tags + versions, or specified repo:tag, for each argument provided.For example uses of this command, refer to the examples section below.OptionsName, shorthandDefaultDescription--output , -oمثالی از نحوه ذخیره داکر های مهم مورد نیاز برنامه نویسی ها دانت کور:در این مثال ها از ایمیج داکرهای زیر در مسیر D:\dockerimage یک پشتیبان گرفته می شودdocker save ocelotapigw -o D:\dockerimage\ocelotapigw.tar
docker save rabbitmq -o D:\dockerimage\rabbitmq.tar
docker save postgres -o D:\dockerimage\aspnetrunbasics.tar
docker save dpage/pgadmin4 -o D:\dockerimage\dpage_pgadmin4.tar
docker save redis -o D:\dockerimage\redis.tar
docker save mcr.microsoft.com/mssql/server -o D:\dockerimage\cr_microsoft_com_mssql_server.tarنحوه بارگذاری یک ایمیج ذخیره شده داکر (Docker):حالا فرض کنید که از یک داکر به روش در قسمت قبل بیان شد یک پشتیبان بر روی کامپیوتر تهیه شده است حالا نیاز است به جای دانلود این ایمیج ان را از روی کامیپوتر خودمان بارگذاری کنیم :docker loadDescriptionLoad an image from a tar archive or STDINUsage$ docker load [OPTIONS]Extended descriptionLoad an image or repository from a tar archive (even if compressed with gzip, bzip2, or xz) from a file or STDIN. It restores both images and tags.For example uses of this command, refer to the examples section below.OptionsName, shorthandDefaultDescription--input , -iRead from tar archive file, instead of STDIN--quiet , -qSuppress the load outputمثال : نحوه بارگذاری ایمیج های داکرهای مهم برای برنامه نویسان دانت کور:docker load -i D:\dockerimage\rabbitmq.tar
docker load -i D:\dockerimage\dpage_pgadmin4.tar
docker load -i D:\dockerimage\redis.tar
docker load -i D:\dockerimage\cr_microsoft_com_mssql_server.tarنحوه نصب مایکروسافت SQL SERVER 2019 بر روی داکر (Docker)همانگونه که مستحضرید متاسفانه شرکت داکر هاب ما رو تحریم کرده برای دور زدن تحریم وارد سایت شکن می شود و مطابق اموزش های ارایه شده در این سایت DNS های خود را تغییر می دهیم  https://shecan.ir/ برای نصب MS SQLSERVER 2019 بر روی داکر ابتدا وارد سایت  داکر هاب (Docker Hub) می شویم و مطابق دستور العمل به شرح زیر عمل می کنیم : https://hub.docker.com/_/microsoft-mssql-server برای دریافت اخرین نسخه SQLSERVER 2019 از دستور زیر استفاده می کنیم:docker pull mcr.microsoft.com/mssql/server:2019-latestسپس از طریق دستور زیر نسبت به اجرای داکر اقدام می  کنیم توجه شود بجای your_password رمزعبور خود رابرای کاربری sa ست می کنیدdocker run -e &amp;quotACCEPT_EULA=Y&amp;quot -e &amp;quotSA_PASSWORD=&lt;your_password&gt;&amp;quot -p 1433:1433 --name sql2019 -d mcr.microsoft.com/mssql/server:2019-latest سپس از طریق دستور زیر sqlcmd را از داخل کانتینر بصورت زیر اجرا می کنیم :docker exec -it sql2019 /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P &lt;your_password&gt;
حالا چند نمونه از دستورات را روی Sqlcmd را اجرا می کنیم:print @@version
goprin @@servername
goselect name from sys.databases
gocreate database db1
gouse db1
goحالا نسبت به دانلود Microsoft SQL Server Management Studio از سایت خود مایکروسافت اقدام می کنیم : https://docs.microsoft.com/en-us/sql/ssms/download-sql-server-management-studio-ssms?view=sql-server-ver15 سپس مطابق شکل زیر نسبت به وصل شدن به SqlServer نصب شده در داکر عمل می کنیم :نحوه پشتیبان گیری (Backup ) و ریستور (Restor)  یک دیتابیس داخل داکر SQLSERVERdocker cpDescriptionCopy files/folders between a container and the local filesystemUsage$ docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-حالا با کمک دستور فوق نسبت به انتقال فایل پشتیبان گیری شده بر روی کامپیوتر خودمان اقدام می کنیم:docker cp sql2019:/var/opt/mssql/data/db1.bak d:\backupحالا فرض کنید که پشتیبان را قبلا تهیه کردید و می خواهید انرا را بر روی دیتابیس خودتان Restor  کنید دوباره از طریق دستور docker cp این بار بصورت معکوس برای کپی پشتیبان به داخل داکر عمل می کنیمdocker cp s d:\backup\db1.bak sql2019:/var/opt/mssql/data/مطابق شکل زیر به قسمت Restore Database وارد می شویم:نسبت به Restore دیتابیس بصورت زیر عمل می کنیم :Persist your dataتغییرات پیکربندی SQL Server داکر اس کیو ال به نحوی است که  فایل های پایگاه داده در کانتینر باقی می مانند حتی اگر کانتینر را با  docker stopو docker start راه اندازی مجدد کنید. با این حال، اگر کانتینر را با docker rm حذف کنید، همه چیز در کانتینر از جمله SQL Server و پایگاه داده‌های شما حذف می‌شود. بخش زیر نحوه استفاده از حجم داده ها را برای حفظ فایل های پایگاه داده خود حتی در صورت حذف کانتینرهای مرتبط توضیح می دهد. https://docs.microsoft.com/en-us/sql/linux/sql-server-linux-docker-container-configure?view=sql-server-ver15&amp;pivots=cs1-bash#persist Mount a host directory as data volumeThe first option is to mount a directory on your host as a data volume in your container. To do that, use the docker run command with the -v &lt;host directory&gt;:docker run -e &amp;quotACCEPT_EULA=Y&amp;quot -e &amp;quotSA_PASSWORD=&lt;your-password&gt;&amp;quot -p 1433:1433 --name sql2017 -v D:/SqlDatabase/data:/var/opt/mssql/data -v D:/SqlDatabase/log:/var/opt/mssql/log -v D:/SqlDatabase/secrets:/var/opt/mssql/secrets -d mcr.microsoft.com/mssql/server:2017-latest docker networkمفاهیم شبکه در داکر خیلی گسترده می باشد و در این مقاله در حد اشنایی با شبکه داکر این موضوع را بررسی می کنیم انواع شبکه در داکر به شرح زیر داریم:User-defined bridge networks are best when you need multiple containers to communicate on the same Docker host.Host networks are best when the network stack should not be isolated from the Docker host, but you want other aspects of the container to be isolated.Overlay networks are best when you need containers running on different Docker hosts to communicate, or when multiple applications work together using swarm services.Macvlan networks are best when you are migrating from a VM setup or need your containers to look like physical hosts on your network, each with a unique MAC address.Third-party network plugins allow you to integrate Docker with specialized network stacks.شبکه bridge :دایور پیشفرض داکر bridge هستش و مواقعی چندتا کانتینر  standalone داریم و این‌ کانینترها با هم دیگه ارتباط دارند از bridge استفاده می‌کنیم. مثلا docker-compse که در بحث برنامه نویسی بیشترین نوع شبکه ای که استفاده می شود این نوع شبکه می باشد که بیشتر مورد بررسی قرار میگرد و سایر شبکه در حد تعریف بررسی می شود. اگر با تکنولوژی‌های مجازی‌ساز(vmware, kvm, ...) کار کرده باشید، باید بهتون بگم شبکه داکر تو حالت bridge با مجازی‌سازها متفاوته!قتی DOCKER یه کانتینر رو اجرا می‌کنه. بصورت پیش فرض یه شبکه BRIDGE میسازه و اون رو NAT میکنه.منظورم از شبکه BRIDGE یعنی یه کارت شبکه مجازی میسازه که بتونه از هاست(سیستم عامل اصلی که داکر روش نصب شده) با container در ارتباط باشه. از طرفی nat هم انجام میده تا کانتینر اینترنت داشته باشه.برای اینکه لیست شبکه‌های داکر رو ببینیم کافیه دستور زیر رو اجرا کنیم:docker network lsدستور ساختن یک شبکه داکر (بصورت پیش فرض از نوع BRIDGE ساخته می شود)docker network create &lt;NAME_OF_NETWORK&gt;docker network create mynetworkحالا اگر بخواهیم یک کانتینر تو این شبکه باشد باید:docker run --network mynetwork-p 8080:80 --name my-container nginx:latestشبکه Host:در این نوع شبکه کانتینر  بطور مستقیم از شبکه ماشین میزبان(سرور) استفاده می‌کند.مثلا یک کانتینر nginx داشته باشیم که شبکه آن از نوع Host باشه با زدن ادرس ماشین میزبان درخواست رو ان پورت مستقیم تحویل کانتینر می شود:شبکه Overlay:کمک overlay می توانیم چند تا docker daemon رو بهم دیگر وصل کرد.به کمک این نوع شبکه می توانیم دو کانتینر داشته باشیم که در دو تا docker daemon جداگانه با همدیگر در ارتباط باشندو می توانیم این ارتباط را رمزنگاری نیز کردشبکه macvlan:با کمک این نوع شبکه می توانیم به کانیتنر های خودمان یک ادرس مک اختصاص دهیم که باعث می شود کانتینر ما در شبکه بعنوان یک دستگاه شناسایی شود طبق مستندات خود سایت داکر این نوع شبکه می تواند بهترین گزینه برای نرم افزارهای قدیمی باشد که مستقیم به شبکه فیزیکی وصل شوند می باشدشبکه none:شبکه را برای کانتینر غیرفعال می کندشبکه Plugin:به کمک این شبکه می توانیم  یک افزونه(plugin) third-party رو نصب و استفاده کرد.dockerfileداکر فایل یک فایل متنی است که در آن مجموعه ایی از دستورات که برای ساختن یک ایمیج داکر نیاز است نوشته می شود و داکر با استفاده از فراخوانی داکر فایل ایمیج را ایجاد می کند برای ساختن ایمیج از دستور زیر استفاده می شودdocker buildDescriptionBuild an image from a DockerfileUsage$ docker build [OPTIONS] PATH | URL | - https://docs.docker.com/engine/reference/commandline/build/ در زیر جدولی آورده ایم مهترین دستورات استفاده شده در داکر فایل ها اشاره شده است:دستورالعمل ها یا instruction های داکر به بزرگ یا کوچک بودن حروف حساس نیستنددستورالعمل های Dockerfile را به ترتیب از بالا به پایین اجرا میکنداولین دستورالعملی که استفاده می شود، FORM است که از آن برای مشخص کردن ایمیج اصلی استفاده میشود و بعد از آن متوان از دستورالعمل های RUN, CMD, FROM, EXPOSE, ENV و غیره استفاده کرد.دستوراتی که با # شروع می شوند، به عنوان یک کامنت عمل میکنندیک داکرفایل نمونه برای دانت کور:dockerfile for .Net Core#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src
COPY [&amp;quotServices/Catalog/Catalog.API/Catalog.API.csproj&amp;quot, &amp;quotServices/Catalog/Catalog.API/&amp;quot]
RUN dotnet restore &amp;quotServices/Catalog/Catalog.API/Catalog.API.csproj&amp;quot
COPY . .
WORKDIR &amp;quot/src/Services/Catalog/Catalog.API&amp;quot
RUN dotnet build &amp;quotCatalog.API.csproj&amp;quot -c Release -o /app/build
FROM build AS publish
RUN dotnet publish &amp;quotCatalog.API.csproj&amp;quot -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT [&amp;quotdotnet&amp;quot, &amp;quotCatalog.API.dll&amp;quot]docker composeابزاری برای ارائه و اجرای برنامه‌هایی است که در اصطلاح مولتی کانتینر بوده و چند کانتینر مختلف دارندdocker-compose.ymlبا استفاده از فایل docker-compose.yml می‌توانید سرویس‌های برنامتان را اجرا و کانفیگ کنید. بعد از آن فقط  با استفاده از یک دستور می‌توانید همه‌‌‌ی سرویس‌هایی را که در فایل yaml خود مشخص کردید، را بسازید و اجرا کنید.برای مثال :اضافه کردن ایمیج مونگودبی به داکر کامپوز فایل برای محیط های مولتی کانتینر داکربرای این کار وارد فایل docker-compose.yml می شویم ابتدا یک سرویس به این فایل بنام storedb اضافه می کنیم و سپس برای اینکه درهنگام نصب و یا حذف کانتینر های اطلاعات دیتابیس حذف نشود و بعبارتی اطلاعات دیتابیس در سیستم فایل ما در یک فایل جداگانه از خود کانتینر نوشته شود یک volumes هم به فایل داکرکامپوز با نام mongo_data اضافه می کنیمdocker-composer
version: &#039;3.4&#039;
services:
  catalogdb:
    image: mongo
  catalog.api:
    image: ${DOCKER_REGISTRY-}catalogapi
    build:
      context: .
      dockerfile: Services/Catalog/Catalog.API/Dockerfile
volumes:
  mongo_data: docker-compose.override.ymlمهم ترین فایل docker-compose.override.yml می رسد, این فایل وقتی که ما دستور می دهیم که داکر کامپوز مجدد کانتینرها را بسازد داکر کامپوز برای رونویسی تنظیمات پروژه از این فایل استفاده می کند
docker-composer.override
version: &#039;3.4&#039;

services:
  catalogdb:
    container_name: catalogdb
    restart: always
    ports:
        - &amp;quot27017:27017&amp;quot
    volumes:
        - mongo_data:/data/db
  catalog.api:
    container_name: catalog.api
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - &amp;quotDatabaseSettings:ConnectionString=mongodb://catalogdb:27017&amp;quot

    depends_on:
      - catalogdb
    ports:
      - &amp;quot8000:80&amp;quotبرای سرویس storedb که همانگونه که مستحضرید هر سرویس به یک داکر کانتینر در نهایت تبدیل می شود ابتدا برای کانتینر یک اسم می دهیم و سپس بهش اعلام می کنیم که اگر در حین استارت کانتینر به مشکل برخورد کرد همیشه کانتینر ریست شود و پورت 27017 برای کانتینر تنظیم کرده و والیومی که دیتاهای مونگودبی باید در ان مسیر نوشته شود را /data/db/ را برای ان تنظیم می کنیمسپس برای کانتینر اصلی پروژه یک نام بنام store.api می دهیم و سپس در پیشنیازهای این سرویس اعلام می کنیم که قبل از استارت این کانتینر باید کانتینر storedb باید ابتدا استارت شده باشد و مشخص می کنیم که پورت ان نیز از 8000 به 80 منتقل شودنمونه از اجرای دستور docker-compose docker-compose -f .\docker-compose.yml -f .\docker-compose.override.yml up -dبا تشکر از مطالعه مقاله بنده https://www.aparat.com/javadjahangiriniopdc/playlists در دوره های آموزش تضمینی مجتمع فنی ارومیه که به صورت خصوصی و عمومی در دو شیوه حضوری و آنلاین برگزار می شود سرفصل های بسیار متنوع و کاربردی را بصورت پروژه محور آموزش داده می شود تا شخص کارآموز بتواند بلافاصله پس از اتمام این دوره در کمترین زمان ممکن وارد بازار کار شود.آموزش تخصص ماست با ما حرفه ای شویدجهت مشاوره با شماره 09149431772 در ارتباط باشید ...</description>
                <category>جواد جهانگیری</category>
                <author>جواد جهانگیری</author>
                <pubDate>Sat, 18 Dec 2021 09:33:27 +0330</pubDate>
            </item>
                    <item>
                <title>آشنایی با امکانات جدید Entity Framework Core (New features)</title>
                <link>https://virgool.io/@javadjahangiri/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%A7%D9%85%DA%A9%D8%A7%D9%86%D8%A7%D8%AA-%D8%AC%D8%AF%DB%8C%D8%AF-entity-framework-core-new-features-wal8zuocl8s3</link>
                <description>به نام آن که جان را فکرت آموخت / چراغ دل به نور جان برافروختبا سلام و تشکر از مطالعه مقالات بنده در کانال ویرگول ، در این مقاله  امکانات جدید EF Core  بررسی می شود. .ایده این سری مقاله های آموزشی از این موضوع سرچشمه می گیرد که بخشی از خوانندگان وجود دارد که به محتوای نوشتاری آنلاین بهتر پاسخ می دهند و ترجیج می دهند مهارت های جدید را به سرعت از طریق خواندن افزایش دهند.این سری اموزش ها با ارایه پکیج آموزش های کاربردی در خصوص C# asp.net core آغاز می شود که انتظار می رود با واکنش مثبت کاربران همراه شود.توجه: این مقاله به مرور زمان، ویرایش و یا تکمیل می‌شود!تقاضا: در صورتی که با مشکل تایپی، دستوری و یا مفهومی در این مقاله برخورد کردید، از شما دوست عزیز و گرامی، صمیمانه تقاضا می‌کنم که اینجانب را مطلع کرده، تا نسبت به تصحیح و یا تکمیل آن، در اسرع وقت، اقدام نمایم.با کمال تشکرجواد جهانگیریشماره تلفن همراه: 09149431772نشانی پست الکترونیکی: javad.jahangiri.niopdc@gmail.comفیلم‌های آموزشی در آپارات:جواد جهانگیری (CTO) - آپاراتفیلم آموزشی در یوتویب: javad jahangiri - YouTubeنسخه مقاله: ۱.۱ - تاریخ بروزرسانی: 1400/09/23در این مقاله به شما توضیح می‌دهم که Entity Framework چیست، چه مزایایی دارد، یک مرور کلی انجام می‌دهم و سپس پیش نیازهای زیر مطالعه می شود: برنامه نویسی (Asynchronous) ناهمزمان  با EF Core مدیریت همروندی یا برنامه نویسی موازی (concurrency) با EF Coreاستفاده از Stored Procedure ها جهت درج، بروز آوری و حذفو در ادامه مقاله امکانات جدید EF Core مطالعه می شود:What&#x27;s New in EF Core 5.0Split queries.Simple logging and improved diagnostics.Many-to-many.Filtered include.Table-per-type (TPT) mapping.Flexible entity mapping.Shared-type entity types and property bags.Required 1:1 dependents.What&#x27;s New in EF Core 6.0temporal tablePre-convention model configurationMigration BundlesCompiled modelsمنبع اموزشی برای این مقاله سایت مایکروسافت می باشد https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-5.0/whatsnew  https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-6.0/whatsnew What is Entity Framework?در مورد Entity framework core می توان گفت که یک data access API می باشد و در حقیقت یک نوع  object relational mapper (ORM) می باشد که می توان از ان بصورت کراس پلتفورم در C# Asp.net Core استفاده کرددر مورد EF Core  انواع دیتابیس ها را پشتیبانی می کندSQL ServerSQLitePostgreSQLMySQLمزیت های EF Coreیکی از مزایای اصلی Ef Core استفاده از LINQ (زبان یکپارچه زبان) است.پیاده سازی توکار (Unit of Work):it will track changeshandle concurrencyراحتی کار با Data binding برنامه نویسی (Asynchronous) ناهمزمان  با EFCore برنامه نویسی Asynchronous با استفاده ی بهینه از منابع سرور، کارایی برنامه را بالا می برد.تعداد thread هایی که در دسترس یک سرور وب قرار دارد محدود است و در مواقعی که بارگذاری سنگین در حال اجرا است، تمامی thread ها بکار گرفته می شوند. در صورت به وجود آمدن چنین شرایطی، سرویس دهنده تا زمانی که تمامی thread ها آزاد نشده اند، قادر به پردازش درخواست ها نخواهد بود. اما در خصوص synchronous code، بسیاری از thread ها با اینکه هیچ کار یا عملیات خاصی را انجام نمی دهند، باز مشغول بوده و قابل دسترس نمی باشند. دلیلش این است که thread ها منتظر هستند که عملیات ورودی/خروجی به اتمام برسد. در رابطه با asynchronous code، هنگامی که فرایندی منتظر اتمام عملیات ورودی/خروجی می باشد، thread آن آزاد شده تا برای پردازش دیگر درخواست ها توسط سرور مورد استفاده قرار گیرد. در نتیجه، asynchronous code امکان و زمینه ی استفاده ی بهینه از منابع سرور را مهیا ساخته و همچنین سرور را قادر می سازد تا بدون هیچ گونه تاخیر ترافیک بیشتری را مدیریت کند.در نسخه های قدیمی تر .NET، کدنویسی و تست آن بسیار پیچیده، مستعد خطا بوده و همچنین خطایابی (debug) آن بسیار دشوار می باشد. در ویرایش C# Asp.net Core  کدنویسی، تست و اشکال زدایی آن به مراتب آسان تر می باشد، از این رو پیشنهاد می کنیم تا حد امکان کدهای ناهمزمان (asynchronous) بنویسید. اگرچه نوشتن کدهای ناهمزمان باعث ورود مقداری سربار (overhead) می شود، در مواقع کم ترافیک، افت کارایی بسیار ناچیز بوده و مشکل بزرگی رخ نمی دهد. این در حالی است که در شرایطی که ترافیک بالا است، افزایش بالقوه ی کارایی چشمگیر خواهد بود.به کد زیر دقت کنیدpublic async Task&lt;actionresult&gt; Index()
{
var departments = db.Departments.Include(d =&gt; d.Administrator);
return View(await departments.ToListAsync());
}چهار تغییر به کد بالا اعمال شده که به query امکان می دهد به صورت ناهمزمان (Async) اجرا گردد:1. متد مورد نظر با کلیدواژه ی asynch علامت گذاری شده که به مترجم یا کامپایلر می فهماند که باید callback هایی را برای بخش های بدنه ی متد ایجاد کرده و شی Task&lt; actionresult&gt;که برگردانده می شود را به صورت خودکار ایجاد کند.2. نوع (type) بازگشتی از ActionResult به &lt;Task&lt; actionresult تبدیل شده است. نوع &lt;Task&lt; t نشانگر عملیات یا کارهای در حال انجام با نتیجه ی type T می باشد.کلیدواژه ی await به فراخوانی web service اعمال شده است. کامپایلر با دیدن این کلیدواژه، در پشت پرده متد مورد نظر را به دو بخش تقسیم می کند. اولین بخش آن متد با عملیاتی که به صورت ناهمزمان راه اندازی (آغاز) شده پایان می یابد و اما دومین بخش آن در یک متد callback قرار داده می شود که پس از اتمام عملیات، فراخوانی می شود.3. نسخه ی ناهمزمان (asynchronous) متد الحاقی (extension method) به نام ToList صدا زده شده است.چرا دستور departments.ToList اصلاح شده اما دستور departments = db.Departments مورد تغییر قرار نگرفته است؟ باید گفت دلیلش این است که تنها آن دستوراتی که باعث می شوند query یا command به پایگاه داده ارسال شود، به صورت ناهمزمان اجرا می شوند. دستور departments = db.Departments یک query تنظیم می کند، اما query تا زمانی که متد ToList فراخوانی نشده، اجرا نمی شود. بنابراین تنها متد ToList به صورت ناهمزمان اجرا می شود.به کدزیر دقت کنید:public async Task&lt;actionresult&gt; Create(Department department)
{
    if (ModelState.IsValid)
    {
        db.Departments.Add(department);
    await db.SaveChangesAsync();
        return RedirectToAction(&amp;quotIndex&amp;quot);
}در متدهای Create، HttpPost Edit و DeleteConfirmed، این فراخوانی متد SaveChanges است که سبب می شود یک دستور اجرا شود، نه دستورهایی نظیر db.Departments.Add(department) که تنها منجر به اصلاح موجودیت ها در حافظه می شوند.نکاتی که در استفاده از برنامه نویسی غیرموازی (asynch) با EFCore بایستی به آن توجه کرد:استفاده از thread ها با async code توصیه نمی شود. به عبارتی دیگر، نبایست چندین عملیات را به طور موازی با استفاده از نمونه ی (context instance) یکسان انجام داد.اگر می خواهید از مزایای بهبود کارایی async code استفاده ی بهینه داشته باشید، لازم است اطمینان حاصل کنید تمامی library package هایی که مورد استفاده قرار می دهید، در صورت فراخوانی متدهای EF ای که باعث ارسال query ها به پایگاه داده می شوند، از async code استفاده کنند.مدیریت همروندی یا برنامه نویسی موازی (concurrency) با EF Coreدر قسمت  قبلی مقاله با نحوه ی بروز رسانی داده ها آشنا شدید. آموزش حاضر به شما می آموزد، زمانی که چند کاربر سعی بر بروز آوری entity یکسان می کنند، چگونه تداخلات (conflict) ناشی از آن را مدیریت کنید.آن صفحاتی که با موجودیت Department کار می کنند را گونه ای ویرایش کنید که بتوانند خطاهای همروندی (concurrency error) را در صورت رخداد آن ها، مدیریت کنند. تصاویر زیر صفحات Index و Delete را به ضمیمه ی خطاهایی که با وقوع تداخل همروندی نمایش داده می شود را نشان می دهد.تداخلات همزمانی (concurrency conflict)زمانی رخ می دهد که کاربری داده های یک entity را برای ویرایش نمایش می دهد و در این میان کاربری دیگر سعی می کند همان داده ها را، قبل از اینکه تغییرات اعمال شده توسط کاربر اول در پایگاه داده نوشته شود، بروز رسانی کند. چنانچه شما شناسایی چنین تداخلاتی را فعال سازی نکنید، آن تغییراتی که توسط آخرین کاربر اعمال می شود، تمامی بروز رسانی دیگر کاربران را بازنویسی می کند. در بسیاری از برنامه ها، این ریسک پذیرفتنی است، یعنی برنامه هایی که کاربران آن محدود است و تعداد اندکی بروز رسانی در آن صورت می گیرد یا بازنویسی برخی تغییرات در آن مشکل بزرگی را ایجاد نمی کند، هزینه ی برنامه نویسی برای همروندی نسبت به مزایایی که به دنبال دارد بیشتر است. در این صورت، نیازی به تنظیم و پیکربندی برنامه برای مدیریت تداخلات همزمانی نیست.کنترل همروندی بدبینانه – قفل گذاری (pessimistic concurrency)یکی از روش های نوشتن برنامه ای که قادر باشد از از دست رفت داده در سناریوهای همروندی جلوگیری کند، اعمال قفل های پایگاه داده است. به این امر کنترل همروندی بدبینانه (pessimistic concurrency) می گویند. در این روش به وسیله قفل گذاری جلوی هرگونه همروندی گرفته می‌شود. تا زمانی که یک دستور درحال اجراست جلوی اجرای دستورهایی که ممکن است مانع اجرای صحیح دستور نخست شوند گرفته می‌شود. برای مثال، پیش از اینکه سطری را از پایگاه داده بخوانیم، یک قفل دسترسی فقط خواندنی (read-only) یا بروز رسانی درخواست می کنیم. )قفل امتیاز دستیابی به یک واحد داده است که توسط سیستم قفل گذاری به یک تراکنش داده می‌شود و یا از او پس گرفته می‌شود.( اگر یک سطر را برای بروز رسانی قفل کنید، هیچ کاربر دیگری قادر به قفل گذاری بر روی آن سطر برای بروز رسانی یا فقط-خواندن نخواهد بود زیرا در آن صورت تنها یک کپی از داده ها در حال ویرایش دریافت خواهد کرد. اگر یک سطر را برای سطح دسترسی فقط خواندن قفل کنید، در آن صورت دیگر کاربران می توانند آن را برای دسترسی فقط-خواندن قفل کنند اما این اجازه را در مورد بروز رسانی نخواهد داشت.اعمال قفل ها و مدیریت آن ها معایبی را نیز به همراه دارد که از جمله می توان به پیچیدگی برنامه نویسی آن اشاره کرد. این کار همچنین لازمه ی منابع مدیریتی بسیار سنگین است. بعلاوه در صورت بالا رفتن تعداد کاربران برنامه ممکن است مشکلاتی در زمینه کارایی به وجود آورده و افت آن را به همراه داشته باشد. بنا به دلایل ذکر شده، تمامی سیستم های مدیریتی پایگاه داده از همروندی بدبینانه پشتیبانی نمی کنند.کنترل همروندی خوش‌بینانه (Optimistic Concurrency)گزینه ی مقابل همروندی بدبینانه، همروندی خوش بینانه (optimistic concurrency) می باشد. در همروندی خوش بینانه به تداخلات همزمانی اجازه ی رخ دادن داده می شود و در صورت روی دادن آن ها، واکنش مناسب صورت می گیرد. به عنوان مثال، کاربری به نام john صفحه ی Departments Edit را اجرا کرده و مقدار Budget را برای فیلد English از $350,000.00 به $0.00 تغییر می دهد.قبل از اینکه john دکمه ی Save را کلیک کند، کاربر دیگری به نام jane همان صفحه را اجرا کرده و فیلد Start Date را از 9/1/2007 به 8/8/2013 تغییر می دهد.ابتدا John دکمه ی Save را کلیک کرده، تغییرات خود را با بازگشت مرورگر به صفحه ی Index مشاهده می کند، سپس jane دکمه ی Save را کلیک می کند. اینکه بعد چه اتفاقی رخ می دهد، بسته به نحوه ی مدیریت تداخلات همروندی توسط شما دارد.1. می توانید حساب اینکه کاربر کدام property را اصلاح کرده نگه دارید و بر اساس آن فقط ستون های مربوطه را در پایگاه داده بروز رسانی نمایید. در مثالی که ذکر شد، هیچ داده ای از دست نمی رود زیرا property های مختلف توسط دو کاربر متفاوت بروز رسانی شده. دفعه ی بعدی که کاربری English department را پیمایش می کند، تغییرات اعمال شده توسط هر دو کاربر را مشاهده خواهد کرد: start date (تاریخ شروع) با مقدار 8/8/2013 و budget ای (بودجه) با مقدار $0.00.این روش بروز رسانی می تواند تعداد رخدادهای تداخل همروندی را که ممکن است منجر به از دست رفت داده شود، کاهش دهد. اما در صورت اعمال تغییرات متقابل به یک property از یک موجودیت، دیگر قادر به جلوگیری از از دست رفت اطلاعات نخواهد بود. اینکه EF به این روش عمل کند، بستگی به نحوه ی پیاده سازی شما از Update code دارد. این کار در یک برنامه ی تحت وب معمولا امکان پذیر و کاربردی نیست، زیرا در آن صورت لازم است برای اینکه علاوه بر مقادیر جدید حساب تمامی مقادیر property های اولیه یک موجودیت را داشته باشیم، مقادیر زیادی از state ها را حفظ و نگه داری کنیم. حفظ و نگهداری مقدار زیادی از state ها می تواند اثر سوء بر کارایی برنامه داشته باشد، زیرا این کار لازمه ی اشغال منابع سرور بوده یا اطلاعات مربوط به آن را می بایست در خود صفحه ی وب (برای مثال در فیلدهای پنهان) و یا یک cookie گنجاند.2. می توانید اجازه دهید تغییرات jane تغییرات اعمال شده توسط john را بازنویسی کند. حال دفعه ی بعدی که کاربری English department را پیمایش می کند، تاریخ 8/8/2013 و مقدار بازگردانده شده ی $350,000.00 را مشاهده می کند. این سناریو، client wins یا last in wins خوانده می شود (بدین معنا که مقادیر ارائه شده توسط client بر مقادیر موجود در انبار داده یا data store اولویت دارد). همان طور که بخش مقدمه ی این آموزش تشریح شد، اگر هیچ کدنویسی برای مدیریت همروندی انجام ندهید، این اتفاق خود به صورت پیش فرض رخ می دهد.3. می توان کاری کرد تغییرات اعمال شده توسط jane در پایگاه داده بروز رسانی نشود. به طور معمول یک پیغام خطا برای کاربر (jane) نمایش می دهیم، وضعیت جاری داده ها را به اطلاع وی می رسانیم، سپس به کاربر مذکور اجازه می دهیم در صورت تمایل (اگر می خواهد همواره اصلاحاتی را ایجاد کند) تغییرات خود را مجددا اعمال نماید. این سناریو تحت عنوان store wins شناخته می شود (بدین معنا که مقادیر انبار داده یا data store بر مقادیر ارائه شده توسط client اولویت دارد). در آموزش حاضر، این روش را پیاده خواهیم کرد. در این روش هیچ تغییری بازنویسی نمی شود، مگر اینکه کاربر قبل آن مطلع شده باشد.تشخیص تداخلات همزمانیمی توان تداخلات همزمانی را با مدیریت خطاهای OptimisticConcurrencyException که توسط EF صادر می شود، برطرف ساخت. برای این که EF تشخیص دهد چه زمانی بایستی خطاهای مربوطه را صادر کند، ابتدا لازم است آن تداخلات را شناسایی کند. بنابراین، می بایست پایگاه داده و data model را به درستی پیکربندی نمود. گزینه هایی که برای فعال سازی conflict detection (تشخیص تداخل) در دست دارید به شرح زیر می باشند:1. در جدول پایگاه داده، یک tracking column (ستون ردیابی) ایجاد می کنیم. این ستون را برای رهگیری و تعیین زمان اصلاح سطر مورد نظر بکار می بریم. سپس می توانیم EF را طوری تنظیم کنیم که آن ستون را در عبارت Where دستورهای Update و Delete اس کیو ال قرار دهد.نوع داده ی ستون مزبور معمولا rowversion می باشد. مقدار rowversion یک sequential number (عدد ترتیبی) است که با هر بروز رسانی سطر مورد نظر، آن عدد افزایش می یابد. در دستور Update یا Delete، عبارت Where مقدار اصلی tracking column (نسخه ی اصلی و اولیه ی سطر مورد نظر) را نگه می دارد. چنانچه سطری که در دست بروزرسانی است توسط کاربر دیگر تغییر داده شود، در آن صورت مقدار موجود در ستون rowversion با مقدار اصلی یا اولیه ی آن متفاوت خواهد بود و از این رو دستور Update یا Delete نمی تواند (بخاطر عبارت Where) سطر مورد نظر را برای آپدیت پیدا کند. هنگامی که EF پی ببرد که هیچ سطری یا رکوردی توسط دستور Update یا Delete بروز آوری نشده (بدین معنا که تعداد سطرهای ویرایش شده برابر با صفر باشد)، در آن صورت EF آن را یک تداخل همروندی درنظر گرفته و رفتار خود را بر اساس آن تنظیم می کند.2. EF را گونه ای تنظیم کنید که مقادیر اولیه ی تمامی ستون های موجود در جدول را داخل عبارت Where دستورات Update و Delete قرار دهد.همان طور که در روش اول تشریح شد، چنانچه از زمانی که سطر برای اولین بار خوانده شد، چیزی در آن تغییر داده شده باشد، در آن صورت عبارت Where هیچ سطری برای بروز رسانی باز نمی گرداند. EF این رخداد را به عنوان یک تداخل همروندی (concurrency conflict) تفسیر می کند. برای آن دسته از جداول پایگاه داده که دربردارنده ی ستون های متعددی هستند، این روش ممکن است باعث ایجاد عبارت های بسیار طولانی Where شود و همچنین شما را مجاب کند مقادیر زیادی از state ها را حفظ و نگداری کنید. پیش تر نیز ذکر شد که حفظ مقادیر زیادی از state ها می تواند کارایی برنامه را تحت تاثیر قرار دهد. بنا به دلایل مذکور، استفاده از این روش توصیه نمی شود.اگر می خواهید این روش را برای کنترل همروندی پیاده کنید، در آن صورت بایستی تمامی خاصیت های غیر کلید اصلی (non-primary-key) را در موجودیتی که می خواهید concurrency آن را ردیابی کنید، با افزودن خصیصه ی ConcurrencyCheck به آن ها علامت گذاری کنید. این تغییر به EF امکان می دهد تمامی ستون ها را در عبارت WHERE دستورهای UPDATE اضافه (include) کند.در ادامه ی این آموزش، یک tracking property rowversion به موجودیت Department اضافه خواهیم کرد، یک controller به همره view هایی ایجاد کرده و درنهایت همه چیز را بررسی کرده و از عملکرد صحیح آن ها اطمینان حاصل می کنیم.افزودن یک property همروندی خوشبینانه به موجودیت Departmentفایل Models\Department.cs را باز کرده و یک tracking property به نام RowVersion اضافه کنید:public class Department
        {
            public int DepartmentID { get; set; }
             [StringLength(50, MinimumLength = 3)]
            public string Name { get; set; }
            [DataType(DataType.Currency)]
            [Column(TypeName = &amp;quotmoney&amp;quot)]
            public decimal Budget { get; set; }
              [DataType(DataType.Date)]
            [DisplayFormat(DataFormatString = &amp;quot{0:yyyy-MM-dd}&amp;quot, ApplyFormatInEditMode = true)]
            [Display(Name = &amp;quotStart Date&amp;quot)]
            public DateTime StartDate { get; set; }
              [Display(Name = &amp;quotAdministrator&amp;quot)]
            public int? InstructorID { get; set; }
             [Timestamp]
            public byte[] RowVersion { get; set; }
              public virtual Instructor Administrator { get; set; }
            public virtual ICollection&lt;course&gt; Courses { get; set; }
}خصیصه ی Timestamp مشخص می کند که این ستون باید در عبارت Where دستورهای Update و Delete ارسالی به پایگاه داده گنجانده شود. خصیصه ی ذکر شده از آنجایی Timestamp خوانده می شود که نسخه های قبلی SQL Server از نوع داده ی timestamp، قبل از اینکه rowversion جایگزین آن شود، استفاده می کردند. معادل rowversion در .NET یک byte array (آرایه ای از نوع byte) می باشد.در صورت تمایل به استفاده از fluent API، می توانید از متد IsConcurrencyToken برای مشخص کردن tracking property مورد نظر استفاده کنید:modelBuilder.Entity&lt;department&gt;()
    .Property(p =&gt; p.RowVersion).IsConcurrencyToken();افزودن یک خاصیت باعث تغییر database model شد، از این باید یک migration دیگر اجرا کنید. در پنجره ی PMC، دستورات زیر را وارد نماییدAdd-Migration RowVersion
Update-Databaseپیشنهاد می شود برای تسلط بیشتر ادامه این قسمت از مقاله از خود سایت مایکروسافت به شرح ذیل مطالعه شود https://docs.microsoft.com/en-us/aspnet/core/data/ef-rp/concurrency?view=aspnetcore-5.0&amp;tabs=visual-studio#conflict-detection-in-ef-core استفاده از Stored Procedure ها جهت درج، بروز آوری و حذف:برخی از DBA ها (مدیران پایگاه داده) ترجیح می دهند از stored procedure ها (رویه های ذخیره شده) برای دسترسی به پایگاه داده استفاده کنند. در ویرایش های پیشین EF می توانستید داده های مورد نیاز را با بکارگیری stored procedure ها بازیابی کنید. این کار به وسیله ی اجرای یک query خام صورت می گرفت. اما این امکان وجود نداشت که به EF COREدستور داد با استفاده از stored procedure عملیات بروز رسانی را انجام دهد. در نسخه ی نوین  EF Core ، به راحتی می توان Code First گونه ای پیکربندی کرد که از stored procedure ها استفاده کند.به مثال زیر توجه کنید :در داخل متد OnModelCreating در داخل کلاس ApplicationDbContext خود کافی است کدی به شکل زیر اضافه شود:modelBuilder.Entity&lt;department&gt;().MapToStoredProcedures();این کد به  EF Core دستور می دهد با استفاده از stored procedure ها، عملیات درج، بروز رسانی و حذف را بر روی موجودیت Department انجام دهد.2. در Package Manage Console، دستور زیر را وارد کنید:add-migration DepartmentSP
فایل Migrations\_DepartmentSP.cs را باز کرده تا کد موجود در متد Up را مشاهده کنید. این متد stored procedure های Insert، Update و Delete را ایجاد می کند:public override void Up()
    {
        CreateStoredProcedure(
    &amp;quotdbo.Department_Insert&amp;quot,
    p =&gt; new
    {
        Name = p.String(maxLength: 50),
        Budget = p.Decimal(precision: 19, scale: 4, storeType: &amp;quotmoney&amp;quot),
        StartDate = p.DateTime(),
       InstructorID = p.Int(),
    },
    body:
        @&amp;quotINSERT [dbo].[Department]([Name], [Budget], [StartDate], [InstructorID])
          VALUES (@Name, @Budget, @StartDate, @InstructorID)
                   DECLARE @DepartmentID int
          SELECT @DepartmentID = [DepartmentID]
          FROM [dbo].[Department]
          WHERE @@ROWCOUNT &gt; 0 AND [DepartmentID] = scope_identity()
                   SELECT t0.[DepartmentID]
          FROM [dbo].[Department] AS t0          WHERE @@ROWCOUNT &gt; 0 AND t0.[DepartmentID] = @DepartmentID&amp;quot
);
        CreateStoredProcedure(
    &amp;quotdbo.Department_Update&amp;quot,
    p =&gt; new
    {
        DepartmentID = p.Int(),
        Name = p.String(maxLength: 50),        Budget = p.Decimal(precision: 19, scale: 4, storeType: &amp;quotmoney&amp;quot),
        StartDate = p.DateTime(),
        InstructorID = p.Int(),
    },
    body:
        @&amp;quotUPDATE [dbo].[Department]
          SET [Name] = @Name, [Budget] = @Budget, [StartDate] = @StartDate, [InstructorID] @InstructorID
          WHERE ([DepartmentID] = @DepartmentID)&amp;quot
);
        CreateStoredProcedure(
    &amp;quotdbo.Department_Delete&amp;quot,
    p =&gt; new
    {
        DepartmentID = p.Int(),
    },
    body:
        @&amp;quotDELETE [dbo].[Department]
          WHERE ([DepartmentID] = @DepartmentID)&amp;quot
); 
 }در Package Manage Console، دستور زیر را وارد نمایید:update-database4. برنامه را در debug mode اجرا کرده، تب Departments را باز کنید، سپس Create New را کلیک نمایید.5. اطلاعات لازم برای یک department جدید را وارد کرده و Create را کلیک نمایید.6. در محیط Visual Studio، اگر به گزارشات (log) در پنجره ی Output توجه کنید، می بینید که یک stored procedure باعث درج یک سطر Department شده است.Code First اسم های پیش فرض برای stored procedure ها ایجاد می کند. در صورت استفاده از یک پایگاه داده ی از پیش موجود، ممکن است لازم باشد اسم stored procedure ها را سفارشی تنظیم کنید تا بتوانید از آن stored procedure هایی که قبلا در پایگاه داده تعریف شده اند، استفاده نمایید.اگر بخواهید کارهایی را که stored procedure های ایجاد شده قادر به انجام آن ها هستند، تنظیم نمایید، در آن صورت بایستی کد ارائه شده توسط scaffolding برای متد Up migrations را که آن stored procedure را ایجاد می کند، ویرایش کنید. در آن صورت تمام تغییرات ایجاد شده توسط شما، هر زمانی که آن migration اجرا می شود منعکس شده و همچنین هنگامی که migrations به صورت خودکار در production پس از نصب (deployment) اجرا می شود، به production database اعمال می گردد.اگر می خواهید Stored procedure موجود را که قبلا در یک migration ایجاد شده، تغییر دهید، در آن صورت می بایست با استفاده از دستور Add-Migration یک migration خالی ایجاد کرده، سپس کدی بنویسید که متد AlterStoredProcedure را فراخوانی کند.شروع به راه اندازی پروژه یک پروژه از نوع C# Asp.net Core Web App از نوع model-view-Controller ایجاد می کنیم :پکیج های زیر را به پروژه اضافه می کنیمInstall-Package Microsoft.EntityFrameworkCore -Version 5.0.12
Install-Package Microsoft.EntityFrameworkCore.Design -Version 5.0.12
Install-Package Microsoft.EntityFrameworkCore.tools -Version 5.0.12
Install-Package Microsoft.EntityFrameworkCore.SqlServer -Version 5.0.12
Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore -version 5.0.12
Install-Package Microsoft.AspNetCore.Identity.EntityFrameworkCore -version 5.0.12
در نهایت به پروژه به شرح ذیل پکیج های ذیل را اضافه می کنیمیک پوشه به پروژه بنام Models اضافه می کنیم و یک کلاس بنام Customer به پروژه اضافه می کنیمusing System.ComponentModel.DataAnnotations;
namespace NewFeaturesEFCore.Models
{
    public class Customer
    {
        public int Id { get; set; }
        [Required]
        public string Name { get; set; }
        [Required]
        public string Email { get; set; }
        public int PhoneNumber { get; set; }
        public byte[] RowVersion { get; set; }
    }
}در Ef Core می تواند به طور خودکار بفهمد که کلید اصلی ما Id خواهد بود و از آنجایی که یک Int است به طور پیش فرض آن را به صورت خودکار افزایش می دهد.سپس به data annotation که به هر فیلد اضافه کرده‌ایم نگاه می‌کند و اطلاعات بیشتری در مورد نحوه راه‌اندازی پایگاه داده به دست می‌آورد، به عنوان مثال، ما یک Required annotation روی نام و ایمیل داریم، Ef core به طور خودکار گزینه not null را در پایگاه داده اختصاص می‌دهد.اکنون اجازه می‌دهیم ApplicationDbContext خود را ایجاد کنیم که بخش اصلی ادغام EF Core در برنامه ما است.اجازه دهید یک پوشه جدید در ریشه برنامه خود ایجاد کنیم و یک کلاس به نام ApplicationDbContext به آن اضافه کنیم.ما از کلاس DbContext که جزء اصلی در Ef Core است، ارث می بریم یک پوشه بنام Data پروژه اضافه می کنیم و یک کلاس بنام ApplicationDbContext به پروژه اضافه می کنیمusing Microsoft.EntityFrameworkCore;
using NewFeaturesEFCore.Models;
namespace NewFeaturesEFCore.Data
{
    public class ApplicationDbContext: DbContext
    {
        // a Db set is where we tell entity framework where to map a class (entity) to a table
        public DbSet&lt;Customer&gt; Customers { get; set; }
        // This is the run time configuration of 
        public ApplicationDbContext(DbContextOptions&lt;ApplicationDbContext&gt; options)
            : base(options)
        { }
        // ModelBuilder is the fluent mapping 
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity&lt;Customer&gt;()
                .Property(a =&gt; a.RowVersion)
                .IsRowVersion(); // Cuncurrency property using fluent mapping
            base.OnModelCreating(modelBuilder);
        }
    }
}کانکشن استرینگ مربوط به دیتابیس SQLSERVER را به فایل appsettings.json پروژه اضافه می کنیم  {
&amp;quotLogging&amp;quot: {
    &amp;quotLogLevel&amp;quot: {
      &amp;quotDefault&amp;quot: &amp;quotInformation&amp;quot,
      &amp;quotMicrosoft&amp;quot: &amp;quotWarning&amp;quot,
      &amp;quotMicrosoft.Hosting.Lifetime&amp;quot: &amp;quotInformation&amp;quot
    }
  },
  &amp;quotAllowedHosts&amp;quot: &amp;quot*&amp;quot,
  &amp;quotConnectionStrings&amp;quot: {
    &amp;quotDefaultConnection&amp;quot: &amp;quotServer=.;Database=NewFeaturesEFCore;Trusted_Connection=True;MultipleActiveResultSets=True&amp;quot
  }
}حالا می بایستی در کلاس Startup میان افزار EFCore را Inject می کنیمpublic void ConfigureServices(IServiceCollection services)
 {
            services.AddDbContext&lt;ApplicationDbContext&gt;(options =&gt;         
       options.UseSqlServer(Configuration.GetConnectionString(&amp;quotDefaultConnection&amp;quot)));
services.AddRazorPages();

 }سپس مایگریشن را ایجاد می کنیم و دیتابیس را بروزرسانی می کنیمAdd-Migration &amp;quotInitial Migration&amp;quot
Update-Databaseدقت شود به جدول مشتریان یک فیلد بنام RowVersion اضافه شده است که برای مفاهیم همزمانی استفاده می شوداجازه دهید اکنون کدی را بنویسیم تا تمام داده های Customer را از پایگاه داده دریافت کنیم، در داخل HomeController خود می توانیم موارد زیر را به Action Index اضافه کنیم. private readonly ILogger&lt;HomeController&gt; _logger;
  private readonly ApplicationDbContext _context;
        public HomeController(ILogger&lt;HomeController&gt; logger, ApplicationDbContext context)        {
            _logger = logger;
            _context = context;
        }
        public async Task&lt;IActionResult&gt; Index()
        {
            var customers = await _context.Customers
                .Where(x =&gt; x.Name.Contains(&amp;quota&amp;quot))
                .OrderBy(o =&gt; o.Name)
                .ToListAsync();
            return View(customers);
        }New Featuresاکنون که مروری اجمالی بر Ef core و ویژگی‌های آن ارائه کرده‌ایم، اجازه دهید در مورد برخی از تغییرات جدیدی که در Ef Core 5 آمده است صحبت کنیم.Debug:نمای اشکال‌زدایی هنگام اجرای دیباگر، می‌توانیم هنگام نگه‌داشتن ماوس روی پرس و جو، گزینه debugView را ببینیم.بنابراین می‌توانیم ببینیم که فیلد Query یک نمایش SQL از کوئری LINQ ما است که می‌توانیم مستقیماً از آنجا کپی کرده و آن را در یک اSQL management studio اجرا کنیم تا خروجی کوئری را آزمایش کنیم و هر مشکلی را که ممکن است با آن مواجه شویم اشکال‌زدایی کنیم. نکته:دقت شود برای اینکه بتوانیم از این حالت استفاده کینم برای دیباگ می بایستی Query را از حالت await خارج کنیم و ToListAsync رادر دو مرحله انجام دهیمیکی دیگر از مواردی که می‌توانیم Query خود را دریافت کنیم، استفاده از متد افزونه در پرس و جو است.ToQueryString()var sqlStr = customers.ToQueryString();
Console.WriteLine(sqlStr);آخرین گزینه فعال کردن گزارش‌های عمومی در سراسر برنامه ما است، در کلاس راه‌اندازی‌مان، جایی که ApplicationDbContext را در DbContextOptions اضافه کرده‌ایم و می‌توانیم لاگ گیری به سیستم را از آنجا فعال کنیم.   public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext&lt;ApplicationDbContext&gt;(options =&gt;
                options.UseSqlServer(Configuration.GetConnectionString(&amp;quotDefaultConnection&amp;quot))
                    .LogTo(Console.WriteLine, LogLevel.Information));
            services.AddControllersWithViews();
        }
نکته :حتما کدها رو به حالت قبل بصورت await و ToListAsync تک مرحله ای برگشت دهید در غیراینصورت در حین اجرای درخواست رو دیتابیس خطا خواهید گرفت Mapping:در EFCORE پیشرفت های جدیدی در روابط ManyToMany ایجاد شد است روابط M2mM فرض کنید ما یک جدول از مشتریان و یک جدول برای گروه ها داریم رابطه Many-To-Many یعنی یک کاربر می تواند به گروه های مختلف تعلق داشته باشد و یک گروه می تواند چندین کاربر داشته باشد.به روشی که در یک پایگاه داده انجام می شود، یک جدول در وسط بین 2 جدولی که روابط Many-to-Many دارند ایجاد می کنیم و آن جدول را Join Table می نامیم که در مورد ما Join Table جدول CustomerGroup است. و هر ردیف داخل آن جدول 1 مشتری را به 1 گروه مرتبط می کندبرای درک بهتر موضوع ابتدا این روابط را به روش قدیمی در EF Core پیاده سازی می کینم و سپس با امکانات جدیدی که به EFCore اضافه شده است با روش جدید پیاده سازی را انجام می دهیم   در حال حاضر ما یک جدول مشتری داریم که اجازه بدهدید 2 جدول دیگر را به پروژه اضافه کنیم و سپس روابط ManyToMany را ایجاد کنیم در پوشه Models اجازه می دهد تا 2 کلاس Group و CustomerGroup اضافه کنیمusing System.Collections.Generic;
namespace NewFeatureEFCore.Models
{
    public class Group
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public ICollection&lt;CustomerGroup&gt; Groups { get; set; }
    }
}
namespace NewFeatureEFCore.Models
{   
 public class CustomerGroup
    {
        public int Id { get; set; }
        public Customer Customer { get; set; }
        public Group Group { get; set; }
    }
}و ما باید کلاس مشتری را به موارد زیر به روز کنیمpublic ICollection&lt;CustomerGroup&gt; Groups {get;set;}مرحله بعدی به روز رسانی ApplicationDbContext استpublic DbSet&lt;Group&gt; Groups { get; set; }
public DbSet&lt;CustomerGroup&gt; CustomerGroups { get; set; }
اجازه می دهد تا اسکریپت های migration خود را ایجاد کنیم تا پایگاه داده ما به روز شود Add-Migration &amp;quotAdded M2M relationships&amp;quot
Update-Databaseحالا ببینیم چگونه می‌توانیم این کد را با EF Core 5 به‌روزرسانی کنیم، اولین کاری که می‌خواهیم انجام دهیم این است که جدول CustomerGroup را حذف کنیم و سپس باید برخی به‌روزرسانی‌ها را در مدل مشتری و گروه انجام دهیم.For the customer ModelFor the Group Modelتعییرات بر روی دیتابیس اعمال می کنیم Add-Migration &amp;quotAdded NewFeature_M2M relationships&amp;quot
Update-Databaseدر اینجا می بینیم که JoinTable را حذف کرده ایم و کار را به EF Core واگذار کرده ایم تا JoinTable را برای ما ایجاد و مدیریت کند. به روز رسانی دیگری که باید انجام دهیم، درخواست LINQ است، زیرا ما دیگر جدول CustomerGroup نداریم، پرس و جو بسیار ساده تر و خواندنی تر به نظر می رسد.var customersElec = _context.Customers
                .Where(x =&gt; x.Groups.Any(g =&gt; g.Name == &amp;quotElectronics&amp;quot));پس چگونه این جادو اتفاق افتاد، EF Core در پس‌زمینه مدل‌هایی را که ما داریم تجزیه و تحلیل کرد و JoinTable را برای ما ایجاد کرد و کنترل آن را در دست گرفت.Inheritance Mappingارث بری در دانت بر اساس  از کلاس هاس base class, sub class است و می‌خواهیم آن‌ها را به یک پایگاه داده رابطه‌ای نگاشت کنیم. به ما اجازه می‌دهد مدل‌های دیگری را اضافه کنیم تا ببینیم قبل از Net 5 چگونه کار می‌کردیم و سپس می‌توانیم نحوه پیاده‌سازی آن را با ویژگی‌های جدید ببینیم. در Net 5 داخل پوشه Models ما اجازه می دهد 2 مدل جدید اضافه کنیم.namespace NewFeatureEFCore.Models
{
    public class VipCustomer:Customer
    {
        public string VipTeir { get; set; }
    }
}using System;
namespace NewFeatureEFCore.Models
{
    public class CorporateCustomer:Customer
    {
        public string CompanyName { get; set; }
        public DateTime StartDate { get; set; }
        public DateTime EndDate { get; set; }
    }
}برای اطلاع از این مدل‌های جدید، باید ApplicationDbSettings خود را به‌روزرسانی کنیم، در روش OnModelCreating، موارد زیر را اضافه می‌کنیم.      public DbSet&lt;VipCustomer&gt; VipCustomer { get; set; }
        public DbSet&lt;CorporateCustomer&gt; CorporateCustomer { get; set; }          modelBuilder.Entity&lt;VipCustomer&gt;();
           modelBuilder.Entity&lt;CorporateCustomer&gt;();
Let us add our migration scripts Add-Migration &amp;quotAdding 2 tables&amp;quot
Update-Databaseاگر به پایگاه داده خود نگاه کنیم، می بینیم که به جای داشتن 3 جدول که نشان دهنده سلسله مراتب مورد نظر ما است، یک مشتری جدول با تمام فیلدهای داخل آن داریم. این روش پیاده سازی TPH - table per hierarchy نامیده می شود.نحوه تمایز هسته Ef بین ردیف کدام جدول از طریق فیلد Discriminator است. این ویژگی از نسخه‌های قبلی در EF Core 5 در Ef core موجود بوده است تا ببینیم چگونه می‌توانیم جداسازی را انجام دهیم.Let us update our ApplicationDbContextmodelBuilder.Entity&lt;VipCustomer&gt;().ToTable(&amp;quotVipCustomers&amp;quot);
 modelBuilder.Entity&lt;CorporateCustomer&gt;().ToTable(&amp;quotCorporateCustomers&amp;quot);Let us add our migrations now
 Add-Migration &amp;quotAdding 2 tables TPT&amp;quot
Update-Databaseحال اگر به پایگاه داده خود نگاه کنیم، به جای داشتن 1 جدول بزرگ که نشان دهنده 3 جدول است، نتیجه واقعاً متفاوت است. بنابراین در حال حاضر مشتری در جدول های مختلف پخش شده است زیرا ما فرمت TPT را پیاده سازی کرده ایم.درک این پیاده سازی ساده است زیرا هر مدل دارای جدولی است که آن را نشان می دهد، با این حال عملکرد در پایگاه داده می تواند ضربه بخورد زیرا هر بار که ما نیاز به پرس و جو از مشتری داریم، پیوستن بین جداول باید اتفاق بیفتد، و اتصال ها عملیات سنگینی در پایگاه داده هستند. . به عنوان مثال، اگر ما 6 سلسله مراتب جدول داشته باشیم، 6 اتصال وجود دارد که یک پرس و جو عملکرد بسیار سنگین است.اگرچه این ویژگی منتشر شده است، روش توصیه شده همچنان استفاده از TPH به طور پیش فرض است.با تشکر از مطالعه مقاله من این مقاله در حین تهیه می باشد و ادامه داردبرای دانلود سورس های این مقاله می توانید از گیت هاب بنده Clone کنید https://github.com/javadjahangiriniopdc/NewFeatureEFCore  https://www.aparat.com/javadjahangiriniopdc در دوره های آموزش تضمینی مجتمع فنی ارومیه که به صورت خصوصی و عمومی در دو شیوه حضوری و آنلاین برگزار می شود سرفصل های بسیار متنوع و کاربردی را بصورت پروژه محور آموزش داده می شود تا شخص کارآموز بتواند بلافاصله پس از اتمام این دوره در کمترین زمان ممکن وارد بازار کار شود.آموزش تخصص ماست با ما حرفه ای شویدجهت مشاوره با شماره 09149431772 در ارتباط باشید ...</description>
                <category>جواد جهانگیری</category>
                <author>جواد جهانگیری</author>
                <pubDate>Tue, 14 Dec 2021 23:54:25 +0330</pubDate>
            </item>
                    <item>
                <title>امن سازی Web Api در  (C# asp.net core) با استفاده از Identity و JWT</title>
                <link>https://virgool.io/@javadjahangiri/%D8%A7%D9%85%D9%86-%D8%B3%D8%A7%D8%B2%DB%8C-web-api-%D8%AF%D8%B1-5-net-%D8%A8%D8%A7-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-identity-%D9%88-jwt-opuptiy2rjfa</link>
                <description>به نام آن که جان را فکرت آموخت / چراغ دل به نور جان برافروختبا سلام و تشکر از مطالعه مقالات بنده در کانال ویرگول در این مقاله به بحث در مورد web api و نحوه امن سازی web api ها و مسایل مربوط به Authentication و Authorization پرداخته می شود در مورد JWT  صحبت می شود  و  از Identity مایکروسافت برای احراز هویت استفاده خواهد شد سعی می شود در یک آموزش کاربردی و پروژه محور نحوه ثبت نام کاربر ، لاگین کاربر ،ایجاد و دریافت توکن و احراز هویت از طریق توکن بررسی شده است.ایده این سری مقاله های آموزشی از این موضوع سرچشمه می گیرد که بخشی از خوانندگان وجود دارد که به محتوای نوشتاری آنلاین بهتر پاسخ می دهند و ترجیج می دهند مهارت های جدید را به سرعت از طریق خواندن افزایش دهند.این سری اموزش ها با ارایه پکیج آموزش های کاربردی در خصوص C# asp.net core آغاز می شود که انتظار می رود با واکنش مثبت کاربران همراه شود.توجه: این مقاله به مرور زمان، ویرایش و یا تکمیل می‌شود!تقاضا: در صورتی که با مشکل تایپی، دستوری و یا مفهومی در این مقاله برخورد کردید، از شما دوست عزیز و گرامی، صمیمانه تقاضا می‌کنم که اینجانب را مطلع کرده، تا نسبت به تصحیح و یا تکمیل آن، در اسرع وقت، اقدام نمایم.با کمال تشکرجواد جهانگیریشماره تلفن همراه: 09149431772نشانی پست الکترونیکی: javad.jahangiri.niopdc@gmail.comفیلم‌های آموزشی در آپارات:جواد جهانگیری (CTO) - آپاراتفیلم آموزشی در یوتویب: javad jahangiri - YouTubeنسخه مقاله: ۱.۱ - تاریخ بروزرسانی: 1400/09/09کاراموزان و دانشجویان عزیز منبع اصلی تهیه این مقاله قسمت امنیت شرکت مایکروسافت به شرح ذیل می باشد https://docs.microsoft.com/en-us/aspnet/core/security/?view=aspnetcore-6.0 همانگونه که مستحضرید این روزها بازار اپلیکیشن های RESTful داغ هستش و دیگر برنامه ها فقط بصورت وب نمی باشد برای مثال برنامه های اندرویدی و یا برنامه های گوشی های ایفون در نظر بگیرد که با سرورهای که بصورت  RESTful سرویس می دهند کار می کند و یا میکروسرویس ها در نظر بگیرد که برای ارتباطات خود از تکنولوژی RESTful استفاده می کنند برای ارتباط با این تکنولوژی از یک قالب خاص داده ای استفاده می شو اول با فرمت XML اطلاعات ارسال و دریافت می شود و د رحال حاظر نیز از فرمت JSON استفاده می شود در حقیقت  JSON یک قالب دیتای می باشد که فارغ از اینکه در سمت کلاینت و یا سرور از چه زبان برنامه نویسی استفاده می شود برای نقل و اطلاعات داده ها استفاده می شودJSON مخفف عبارت JavaScript Object Notation (نشانه گذاری شی جاوا اسکریبت) می باشد در حقیقت یک قالب سبک وزن برای دخیره و حمل و نقل دیتا می باشد . مثال زیر یک شئ با نام “employees” به معنای کارمندان تعریف کرده است که مقدار این شی حاوی آرایه‌ای با ۳ عنصر است. که هر عنصر آرایه یک شئ است که مشخصات یک کارمند را دربر می‌گیرد.{
&amp;quotemployees&amp;quot:[
{&amp;quotfirstName&amp;quot:&amp;quotJohn&amp;quot, &amp;quotlastName&amp;quot:&amp;quotDoe&amp;quot},
{&amp;quotfirstName&amp;quot:&amp;quotAnna&amp;quot, &amp;quotlastName&amp;quot:&amp;quotSmith&amp;quot},
{&amp;quotfirstName&amp;quot:&amp;quotPeter&amp;quot, &amp;quotlastName&amp;quot:&amp;quotJones&amp;quot}
]
}قواعد نحوه نوشتن JSONداده‌ها در جفت‌هایی بصورت نام/مقدار (name/value) قرار می‌گیرد.داده‌ها با علامت کاما از هم جدا می‌شوند.علامت‌های { } اشیاء را نگه می‌دارند.علامت‌های [ ] آرایه‌ها را نگه می‌دارند.JWTبرای درک توکن JWT ابتدا وارد سایت زیر می شویم : https://jwt.io/ دقت کنید JWT مخفف JSON Web Token می باشددر توکن قسمت قرمز رنگ در حقیقت همان Header بوده و قسمت بنفش هم قسمت Payload بوده و قسمت آبی رنگ هم قسمت Signature هستش دو روش کلی و پرکاربرد اعتبارسنجی سمت سرور، برای برنامه‌های سمت کاربر وب وجود دارند:روش اول Cookie-Based Authentication که پرکاربردترین روش بوده و در این حالت به ازای هر درخواست، یک کوکی جهت اعتبارسنجی کاربر به سمت سرور ارسال می‌شود (و برعکس).روش دوم Token-Based Authentication که بر مبنای ارسال یک توکن امضا شده به سرور، به ازای هر درخواست است.مزیت‌های استفاده‌ی از روش مبتنی بر توکن چیست؟دامنه‌های متفابل Cross-domain / CORS: کوکی‌ها و CORS آنچنان با هم سازگاری ندارند، چون صدور یک کوکی وابسته‌ است به دومین مرتبط به آن و استفاده‌ از آن در سایر دومین‌ها عموما پذیرفته شده نیست، اما روش مبتنی بر توکن، وابستگی به دومین صدور آن‌ را ندارد و اصالت آن بر اساس روش‌های رمزنگاری تصدیق می‌شود.بدون حالت بودن و مقیاس پذیری سمت سرور: در حین کار با توکن‌ها، نیازی به ذخیره‌ اطلاعات داخل سشن سمت سرور نیست و توکن موجودیتی است خود شمول (self-contained). به این معنا که حاوی تمام اطلاعات مرتبط با کاربر بوده و محل ذخیره‌ی آن در local storage و یا کوکی سمت کاربر می‌باشد. (البته اگر نیاز به مدیریت توکن‌ها داشته باشید نباید این مورد درنظر بگیرید)توزیع برنامه با CDN: حین استفاده از روش مبتنی بر توکن، امکان توزیع تمام فایل‌های برنامه (جاوا اسکریپت، تصاویر و غیره) توسط CDN وجود دارد و در این حالت کدهای سمت سرور، تنها یک API ساده خواهد بود.عدم در هم تنیدگی کدهای سمت سرور و کلاینت: در حالت استفاده‌ از توکن، این توکن می‌تواند از هرجایی و هر برنامه‌ای صادر شود و در این حالت نیازی نیست تا وابستگی ویژه‌ای بین کدهای سمت کلاینت و سرور وجود داشته باشد.سازگاری بهتر با سیستم‌های موبایل: در حین توسعه‌ برنامه‌های بومی پلتفرم‌های مختلف موبایل، کوکی‌ها روش مطلوبی جهت کار با APIهای سمت سرور نیستند. تطابق یافتن با روش‌های مبتنی بر توکن در این حالت ساده‌تر است.باگ CSRF: از آنجایی که از کوکی استفاده نمی‌شود، نیازی به نگرانی در مورد حملات CSRF نیست. چون دیگر برای مثال امکان سو استفاده‌ از کوکی فعلی اعتبارسنجی شده، جهت صدور درخواست‌هایی با سطح دسترسی شخص لاگین شده وجود ندارد، چون این روش کوکی را به سمت سرور ارسال نمی‌کند.کارآیی بهتر: حین استفاده‌ از توکن‌ها، به علت ماهیت خود شمول آنها، رفت و برگشت کمتری به بانک اطلاعاتی صورت گرفته و سرعت بالاتری را شاهد خواهیم بود. (البته اگر نیاز به مدیریت توکن‌ها داشته باشید نباید این مورد درنظر بگیرید)امکان نوشتن آزمون‌های یکپارچگی ساده‌تر: در حالت استفاده‌ از توکن‌ها آزمودن یکپارچگی برنامه نیازی به رد شدن از صفحه‌ی لاگین را ندارد و پیاده سازی این نوع آزمون‌ها ساده‌تر از قبل است.استاندارد بودن: امروزه همینقدر که استاندارد JSON Web Token را پیاده سازی کرده باشید، امکان کار با انواع و اقسام پلتفرم‌ها و کتابخانه‌ها را خواهید یافت.اما JWT یا JSON Web Token چیست؟توضیح: JSON Web Token یا JWT یک استاندارد وب است (RFC 7519) که روشی فشرده و خود شمول (self-contained) را جهت انتقال امن اطلاعات بین مقاصد مختلف را توسط یک شی JSON تعریف می‌کند. این اطلاعات قابل تصدیق و اطمینان هستند، از این‌ رو که به صورت دیجیتال امضا می‌شوند. JWTها توسط یک کلید خصوصی (با استفاده از الگوریتم HMAC) و یا یک جفت کلید خصوصی و عمومی (توسط الگوریتم RSA) قابل امضا شدن هستند.در این تعریف واژه‌هایی مانند «فشرده» و «خود شمول» بکار رفته‌اند: - «فشرده بودن»: اندازه‌ی شی JSON یک توکن در این حالت کوچک بوده و به سادگی از طریق یک URL و یا پارامترهای POST و یا داخل یک HTTP Header قابل ارسال است و به دلیل کوچک بودن این اندازه انتقال آن نیز سریع است. - «خود شمول»: بار مفید (payload) این توکن شامل تمام اطلاعات مورد نیاز جهت اعتبارسنجی یک کاربر است تا دیگر نیازی به کوئری گرفتن هر باره‌ از بانک اطلاعاتی نباشد (در این روش مرسوم است که فقط یکبار از بانک اطلاعاتی کوئری گرفته شده و اطلاعات مرتبط با کاربر را امضای دیجیتال کرده و به سمت کاربر ارسال می‌کنند).جوت‌ها دارای سه قسمت است و این قسمت‌ها با نقطه از هم جا شدند، مانند: xxxxx.yyyyy.zzzzz که شامل سه بخش: header.payload.signature می‌باشند و هر بخش با الگوریتم Base64 اینکد می‌شود. نمونه‌ای از یک توکن جوت:1eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.XbPfbIHMI6arZ3Y922BhjWgQzWXcXNrz0ogtVhfEd2oبخش Header:بخش Header عموما دارای دو قسمت است که نوع توکن و الگوریتم مورد استفاده‌ توسط آن را مشخص می‌کند. نوع توکن در اینجا JWT است و الگوریتم‌های مورد استفاده، عموما  HMAC SHA256 و یا RSA هستند. نمونه اطلاعات دیکد شده بخش هدر:1234{
   &amp;quotalg&amp;quot: &amp;quotRS256&amp;quot,
   &amp;quottyp&amp;quot: &amp;quotJWT&amp;quot
}بخش payload:بخش payload یا «بار مفید» توکن، شامل claims است، منظور از claims اطلاعاتی است در مورد موجودیت مدنظر (عموما کاربر) و یک سری متادیتای اضافی. سه نوع claim وجود دارند:نوع اول Reserved claims: یک سری اطلاعات مفید و از پیش تعیین شده‌ غیراجباری هستند مانند:iss یا صادر کنند، exp یا تاریخ انقضا، sub یا عنوان (subject) و aud یا مخاطب (audience)نوع دوم Public claims: می‌تواند شامل اطلاعاتی باشد که توسط IANA JSON Web Token Registry پیشتر ثبت شده‌است و فضاهای نام آنها تداخلی نداشته باشند.نوع سوم Private claims: ادعای سفارشی هستند که جهت انتقال داده‌ها بین مقاصد مختلف مورد استفاده قرار می‌گیرند.نمونه اینکد شده بخش payload توکن:123456{
   &amp;quotexp&amp;quot: 1520507268,
   &amp;quotsub&amp;quot: 582946,
   &amp;quotname&amp;quot: &amp;quotErFUN KH&amp;quot,
   &amp;quotadmin&amp;quot: true
}در نمونه بالا دو دیتای اول از نوع Reserved claims می‌باشد و دو دیتای آخر از نوع Private claims.به طور استاندارد بخش Reserved claims می‌تونه شامل این موارد باشه:فیلد iss یا issuer: صادر کننده توکن در این قسمت مشخص میشه، برای مثال مقدارش می‌تونه &quot;hesabfun.com&quot; باشه.فیلد sub یا subject: در اینجا موضوع اصلی توکن مطرح میشه، مثلا موضوع توکن ما شناسایی کاربرانه، پس یوزر آیدی کاربر توش قرار میدیم تا متوجه بشیم کسی که توکن برامون ارسال کرده کیه.فیلد aud یا audience: در این قسمت مشخص می‌کنیم این توکن باید کجا مورد استفاده قرار بگیره، این مواقعی کاربرد داره که شما چندتا سرور داشته باشید و همه از یک کلید خصوصی برای امضا استفاده می‌کنند. برای مثال مقدارش می‌تونه &quot;https://blog.hesabfun.com&quot; باشه.فیلد exp یا expiration: در این قسمت مشخص میکنیم توکن تا چه زمانی اعتبار داره، این تاریخ بصورت Unix time مشخص می‌کنیم.فیلد nbf یا not before: در این قسمت مشخص می‌کنیم توکن از چه تاریخی به بعد باید مورد مورد پردازش قرار بگیره، یعنی ممکنه توکن زودتر ایجاد کنیم ولی فعلا اجازه استفاده از اون نداشته باشند.فیلد iat یا issuedAt: تاریخ ایجاد توکن به صورت Unix time اینجا قرار میدیم، بیشتر برای اینکه متوجه بشیم توکن جدیده یا نه استفاده میشه.فیلد jti یا jwt id: آیدی منحصر به فرد برای هر توکن، اگه سیستم مدیریت توکن تلگرام دیده باشید متوجه میشید میتونه همچین استفاده‌ای داشته باشه، بهتره برای بلاک کردن، کل توکن تو دیتابیس قرار ندید و به هرکدوم یه آیدی بدید اینجوری دیتابیس سبک‌تری دارید.این مقادیر همینجا تموم نمیشه، میتونید نگاهی به لیست مایکروسافت کنید، ولی بهتره خیلی شلوغش نکنید، مهم همین‌ها هستند که خیلی وقت‌ها استفاده نمیشن نهایتا sub و exp استفاده می‌کنند.بخش signature:تا اینا دیدیم همه دیتاهای با الگوریتم بیس۶۴ اینکد شد که به راحتی تو هرسیستمی دیکد میشه (اگه با این شیوه آشنا نیستید باید بگم فقط کاراکترهای غیر مجاز به حروف تبدیل میکنه، مقاله ویکی‌پدیا بخونید) و هرکسی می‌تونه همچین توکنی بسازه و برای ما ارسال کنه ولی نه با وجود بخش سوم (امضا).همونطوری که می‌بینید بخش اول (هدر) با بخش دوم (پیلود) جمع شده و بعد با کلید خصوصی (کلید خصوصی فقط در سرور موجوده) رمز میشه، این به عنوان بخش سوم یا امضا توکن ما استفاده میشه، درصورتی که اطاعات پیلود دست کاری بشه امضا برای سرور معتبر نیست، همچنین چون کاربران کلید خصوصی ندارند نمی‌تونند خودشون توکن تولید کنند.همینطور درنظر داسته باشید اطلاعات حساس مثل پسورد یا... داخل توکن نذارید چون هرکسی می‌تونه به سادگی توکن باز کنه و دیتای داخلش بخونه، ولی اگر واقعا نیازه اطلاعات حساس داخلش بذارید باید از JWE استفاده کنید.نکته:توجه شود با عنایت به اینکه اطلاعات در توکن Jwtرمز نشده و فقط بصورت base64 اینکد می شود لذا ما در سامانه های که نیاز به امنیت بیشتری دارند از پروتکل https برای زمز نگاری اطلاعات استفاده می کنیمچرخه حیات jwt1.ابتدا کاربر به نام کاربری و رمز صحیح در سامانه ما login می کند2.در صورت موفق بودن login به سامانه برنامه یک توکن jwt ایجاد می کند و این توکن را به سمت کلاینت ارسال می کند در توکن در امضا اطلاعات header و payload با یک کلید رمز می شود توجه شود اطلاعات header و Payload خودشان رمز نشده و بصورت base64 فقط encode  می شود و براحتی می شود این اطلاعات را decode کرد.3.کلاینت این توکن را ذخیره کرده و بخاطر ماهیت Stateless بودن پروتکل http بهمراه هر درخواست در Header درخواست توکن jwt را نیز ارسال می کند4.سرور توکن ارسال بهمراه درخواست دریافت کرده قسمت امضا را با کلیدی که در روی سرور می باشد از رمز خارج می کند و با اطلاعات Headerو payload تطبیق می دهد در صورت درست بودن امضا سرور به درخواست Response می دهد و در غیر اینصورت خطای عدم احراز هویت می دهدویدیوی پیشنهادیدر این سری از اموزش های خودم  به اموزش کاربردی ایجاد web api در asp.net core با jwt بهمراه swagger پرداخته می شود. https://www.aparat.com/v/qAjUN  ASP.NET Core authenticationAuthentication ( احراز هویت) :   وظیفه اینو داره که هویت کاربر رو بررسی کنه. آیا کاربر وجود داره یا نه؟ آیا مشخصات وارد شده کاربر صحیح هست یا نه؟ اصلا کاربری با این مشخصات وحود داره؟ (کلا کارش یقه کاربر رو گرفتنه.)Authentication  فرآیند تعیین هویت کاربر است.Authorization (مجوز) :   خب حالا که فهمیدیم کاربر وجود داره و مشخصاتی که وارد کرده صحیح بوده، حالا باید بررسی کنیم کاربر عزیزمون چه دسترسی هایی(Permission) داره.(همون Role هایی که براش انتخاب میکنیم و میره توی قسمت های مختلف سایت حال میکنه واسه خودش)Authorization ?فرآیند تعیین اینکه آیا کاربر به یک منبع دسترسی دارد یا خیر.در ASP.NET Core،  احراز هویت توسط سرویس IAuthenticationService انجام می شود که این سرویس توسط Middleware احراز هویت استفاده می شود.سرویس احراز هویت (authentication service) از کنترل کننده های احراز هویت ثبت شده  (registered authentication handlers) برای تکمیل اقدامات مربوط به احراز هویت استفاده می کند.نمونه هایی از اقدامات مرتبط با احراز هویت (  registered authentication handlers ) به شرح ذیل می باشد:احراز هویت یک کاربرهنگامی که یک کاربر احراز هویت نشده سعی می کند به یک منبع محدود دسترسی پیدا کند، وارد عمل می شود.کنترل کننده های احراز هویت ثبت شده (registered authentication handlers ) و گزینه های پیکربندی آنها &quot;schemes&quot; نامیده می شوند.برای ثبت  Authentication schemes  می بایستی وارد Startup  و قسمت ConfigureService می شویم و به شرح ذیل عمل می کنیم:روش اول که بیشتر استفاده می شود با فراخوانی extention متد خاص اسکیمای مورد نظر بعد از فراخوانی services.AddAuthentication برای مثال AddJwtBearer یا AddCookie را می توان نام برد . این اکستنشن متدها از AuthenticationBuilder.AddScheme برای ثبت اسکمیا به شرح ذیل استفاده می کنندروش دوم که کمتر استفاده می شود با فراخوانی مستقیم AuthenticationBuilder.AddScheme می باشد.برای مثال ) این کد نحوه ثبت authentication services and handlers برای  ookie and JWT bearer authentication schemes به شرح ذیل را نمایش می دهدservices.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) 
   .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =&gt; Configuration.Bind(&amp;quotJwtSettings&amp;quot, options))    
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =&gt; Configuration.Bind(&amp;quotCookieSettings&amp;quot, options));
پارمتر JwtBearerDefaults.AuthenticationScheme در AddAuthentication نام اسکیمای می باشد که در مواقعی که اسکیمای مشخص درخواست نشده است استفاده می شوداگر اسکیماهای مختلفی استفاده شود authorization policies (or authorization attributes) می تواند اسکیمای احراز هویت (و یا اسکیماهای) که کاربر برای احزار هویت به ان وابسته است را مشخص کنددرمثال بالا، cookie authentication scheme را می توان با مشخص کردن نام آن  ((CookieAuthenticationDefaults.AuthenticationScheme بطور پیش فرض) ،گرچه هنگام فراخوانی AddCookie می توان نام دیگری ارائه داد).در برخی موارد، با فراخوانی AddAuthentication به طور خودکار با روش های دیگر  extension methods انجام می شود. به عنوان مثال، هنگام استفاده از ASP.NET Core Identity اکتنشن متد AddAuthentication به صورت داخلی فراخوانی می شود.برای استفاده از  Authentication middleware می بایستی extension method  (اکستنشن متد) UseAuthentication بر روی app&#x27;s IApplicationBuilder فراخوانی شود.فراخوانی UseAuthentication میان افزاری را که ازregistered authentication schemes ثبت شده قبلی استفاده می کند را  ثبت می کند.قبل از هر میان افزاری که به احراز هویت کاربران بستگی دارد، UseAuthentication را فراخوانی کنید. هنگام استفاده از مسیریابی  endpoint routing،  فراخوانی UseAuthentication باید انجام شود.پس از UseRouting، به طوری که اطلاعات مسیر برای تصمیم گیری های احراز هویت در دسترس باشد.قبل از UseEndpoints، به طوری که کاربران قبل از دسترسی به نقاط پایانی احراز هویت شوند.حتما برای درک بهتر مطالب مقاله زیر مطالعه شود: https://docs.microsoft.com/en-us/aspnet/core/security/authentication/?view=aspnetcore-6.0 تکنولوژِی Swagger یا OpenAPIتکنولوژِی Swagger یا OpenAPI یک استاندارد مستقل از زبان است که برای توصیف API های REST است. در واقع Swagger هم به کامپیوتر و هم به انسان این امکان را می دهد که قابلیت های REST API را بدون دسترسی مستقیم به source code درک کنند. اهداف اصلی آن عبارتند از:میزان کار مورد نیاز برای اتصال سرویس های جدا شده را به حداقل برسانید.زمان مورد نیاز برای مستندسازی دقیق سرویس ها را کاهش دهید.بررسی OpenApi با Swaggerپروژه Swagger در سال 2015 به ابتکار OpenAPI اهدا شد و از آن زمان به عنوان OpenAPI نامیده می شود. هر دو نام به جای یکدیگر استفاده می شوند. با این حال “OpenAPI” به مشخصات اشاره دارد و “Swagger” به گروه های open-source و تجاری از SmartBear اشاره می کند که با مشخصات OpenAPI کار می کنند. محصولات متن باز یا open-source بعدی مانند OpenAPIGenerator نیز با وجود عدم انتشار توسط SmartBear تحت نام خانوادگی Swagger قرار می گیرند.به طور خلاصه می توان گفت:OpenAPI یک استاندارد است.Swagger ابزاری است که از مشخصات OpenAPI استفاده می کند. به عنوان مثال: OpenAPIGenerator و SwaggerUI.استاندارد OpenAPI (openapi.json)استاندارد OpenAPI سندی است که قابلیت های API شما را توصیف می کند. این سند بر اساس XML و attribute annotation ها در کنترلرها و مدل ها است. این بخش اصلی جریان OpenAPI است و برای هدایت ابزارهایی مانند SwaggerUI استفاده می شود. به طور پیش فرض، نام آن openapi.json استرابط کاربری Swaggerرابط کاربری Swagger یک UI مبتنی بر وب ارائه می دهد که اطلاعات مربوط به سرویس را با استفاده از مشخصات OpenAPI ایجاد شده ارائه می دهد. درواقع Swashbuckle و NSwag شامل یک نسخه تعبیه شده از رابط کاربری Swagger هستند، به طوری که می توان آن را با استفاده از یک middleware در برنامه ASP.NET Core شما میزبانی کرد.مستندسازی API اغلب یک کار خسته کننده و در عین حال ضروری تلقی می شود. با استفاده از OpenAPI یا Swagger که به خوبی با ASP.NET Core ادغام شده است، می توانید این کار را بر اینکار را انجام دهیدMicrosoft.AspNetCore.Authentication.JwtBearerASP.NET Core middleware that enables an application to receive an OpenID Connect bearer tokenBearer Authenticationاحراز هویت حامل  (Bearer authentication)که احراز هویت توکن (token authentication) نیز نامیده می شود) یک طرح احراز هویت HTTP است که شامل توکن های امنیتی (security tokens)به نام توکن های حامل (bearer tokens)است. نام &quot;احراز هویت حامل&quot; (Bearer authentication) را می توان به عنوان &quot;give access to the bearer of this token&quot; درک کرد. توکن حامل (bearer token) یک رشته رمزی است که معمولاً توسط سرور در پاسخ به درخواست ورود ایجاد می شود. هنگام درخواست برای منابع محافظت شده، مشتری باید این نشانه را در هدر Authorization ارسال کند https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.authentication.jwtbearer?view=aspnetcore-6.0 AddJwtBearer Method تنظیمات متد AddJwtBearer یک چنین مفاهیمی را به همراه دارند:- تنظیم SaveToken به true، به این معنا است که می‌توان به توکن دریافتی از سمت کاربر، توسط متد HttpContext.GetTokenAsync در کنترلرهای برنامه دسترسی یافت.در قسمت تنظیمات TokenValidationParameters آن:- کار خواندن فایل appsettings.json برنامه جهت تنظیم صادر کننده و مخاطبین توکن انجام می‌شود. سپس IssuerSigningKey به یک کلید رمزنگاری متقارن تنظیم خواهد شد. این کلید نیز در تنظیمات برنامه قید می‌شود.- تنظیم ValidateIssuerSigningKey به true سبب خواهد شد تا میان‌افزار اعتبارسنجی، بررسی کند که آیا توکن دریافتی از سمت کاربر توسط برنامه‌ی ما امضاء شده‌است یا خیر؟- تنظیم ValidateLifetime به معنای بررسی خودکار طول عمر توکن دریافتی از سمت کاربر است. اگر توکن منقضی شده باشد، اعتبارسنجی به صورت خودکار خاتمه خواهد یافت.- ClockSkew به معنای تنظیم یک تلرانس و حد تحمل مدت زمان منقضی شدن توکن در حالت ValidateLifetime است. در اینجا به صفر تنظیم شده‌است.سپس به قسمت JwtBearerEvents می‌رسیم:- OnAuthenticationFailed زمانی فراخوانی می‌شود که اعتبارسنج‌های تنظیمی فوق، با شکست مواجه شوند. برای مثال طول عمر توکن منقضی شده باشد و یا توسط ما امضاء نشده‌باشد. در اینجا می‌توان به این خطاها دسترسی یافت و درصورت نیاز آن‌ها را لاگ کرد.- OnChallenge نیز یک سری دیگر از خطاهای اعتبارسنجی را پیش از ارسال آن‌ها به فراخوان در اختیار ما قرار می‌دهد.- Received برای حالتی است که توکن دریافتی، توسط هدر مخصوص Bearer به سمت سرور ارسال نمی‌شود. عموما هدر ارسالی به سمت سرور یک چنین شکلی را داردOnTokenValidated پس از کامل شدن اعتبارسنجی توکن دریافتی از سمت کاربر فراخوانی می‌شودclaim چیست و چه ارتباطی به سطح دسترسی امنیتی دارد؟امروزه بنای امنیت براساس Claim  در نرم افزارهای مبتنی بر وب دارای رویکرد بسیار خوبی است .اما همه درک نمی کنند  که claim چیست و چرا باید در نرم افزارهای کاربردی مورد استفاده قرار گیرد. البته مهم تراز معماری و نیازسنجی برای طراحی یک اپلیکیشن، مکانیزم امنیت براساس دسترسی نقش مورد نظر یا براساس امنیت claim یا حتی بدون هیچ  احراز هویت و بدون مکانیزم دسترسی است .با این اوصاف claim یک ویژگی است که برای توصیف کردن یک موضوع استفاده میشود(از دید ما ،شناسایی هویت).شناسایی تشخیص هویت یک روش متداول است که در برنامه های کاربردی برای بدست آوردن اطلاعات لازم در مورد هویت کاربران داخل سازمان خودمان ، سازمان های دیگر و در اینترنت مورد استفاده قرار میگیرد.این اصطلاح همانند تفاوت در اختیارات در زمینه دسترسی ها روابط گسترده ای دارد. به عنوان مثال ، سن کاربران در تماشای یک فیلم ترسناک یک نوع سطح دسترسی است. بر اساس claim ، این یک مجوز تشخیص هویت است ، به عنوان مثال : همه افراد دارای سن بالاتر از 16 می توانند (بعضی کار ها را )انجام دهند. اما این امر برای شناسایی هویت ها در مورد ویژگی هایی همانند &quot;سن&quot;  وقتی &quot; همه افرادی که میتوانند فیلم ترسناک نگاه کنند باید ..... ساله  باشند&quot; آسان نیست.بنابراین claim یک ویژگی از هویت است که مجوز ها را تعریف میکند ، زمانیکه مجوزهای درستی  برای انجام دادن کاری هستند. Identity on ASP.NET CoreAsp.net Identity يك راه جديد براي احراز هويت در پروژه هاي دات نت توسط مايكروسافت مي باشد. آن يك مكانيسم رايج براي به كارگيري در تمام فريم ورك هاي مايكروسافت از جمله web form، mvc، web api و غيره مي باشد. آن متدها و ويژگي هايي را براي مديريت كارربان و نقش ها در دات نت در اختيار ما قرار مي دهد.Identity در ASP.NET Core ، یک سیستم عضویت است که قابلیت ورود به سیستم را به برنامه ‏های ASP.NET Core اضافه می‏کند.کاربران می توانند با اطلاعات ورود به سیستم ذخیره شده در Identity یک حساب ایجاد کنند یا می توانند از یک ارائه دهنده ی( login provider) ورود خارجی استفاده کنند.فراهم کننده های ورود به سیستم خارجی شامل Facebook، Google، Microsoft Account، و Twitter هستند.Identity می تواند با استفاده از پایگاه داده ی SQL Server جهت ذخیره ی نام های کاربری، رمز عبورها، و داده های پروفایل پیکربندی شود.همچنین، انباره ی پایدار دیگری می تواند مورد استفاده قرار بگیرد، برای مثال، Azure Table Storage.همانطور که داستان سیستم عضویت ASP.NET طی سالیان تغییر و رشد کرده است، تیم ASP.NET نیز آموخته‌های زیادی از بازخورد‌های مشتریان شان بدست آورده اند.این پیش فرض که کاربران شما توسط یک نام کاربری و کلمه عبور که در اپلیکیشن خودتان هم ثبت شده است به سایت وارد خواهند شد، دیگر معتبر نیست. دنیای وب اجتماعی شده است. کاربران از طریق وب سایت‌ها و شبکه‌های اجتماعی متعددی با یکدیگر در تماس هستند، خیلی از اوقت بصورت زنده! شبکه هایی مانند Facebook و Twitter.با در نظر گرفتن تغییراتی که در توسعه اپلیکیشن‌های وب بوجود آمده ASP.NET Identity با اهداف زیر متولد شد:یک سیستم هویت واحد (One ASP.NET Identity system)سیستم ASP.NET Identity می‌تواند در تمام فریم ورک‌های مشتق از ASP.NET استفاده شود. مانند ASP.NET MVC, Web Forms, Web Pages, Web API و SignalRاز این سیستم می‌توانید در تولید اپلیکیشن‌های وب، موبایل، استور (Store) و یا اپلیکیشن‌های ترکیبی استفاده کنید.سادگی تزریق داده‌های پروفایل درباره کاربرانروی الگوی دیتابیس برای اطلاعات کاربران و پروفایل‌ها کنترل کامل دارید. مثلا می‌توانید به سادگی یک فیلد، برای تاریخ تولد در نظر بگیرید که کاربران هنگام ثبت نام در سایت باید آن را وارد کنند.کنترل ذخیره سازی/واکشی اطلاعاتبصورت پیش فرض ASP.NET Identity تمام اطلاعات کاربران را در یک دیتابیس ذخیره می‌کند. تمام مکانیزم‌های دسترسی به داده‌ها توسط EF Code First کار می‌کنند.از آنجا که روی الگوی دیتابیس، کنترل کامل دارید، تغییر نام جداول و یا نوع داده فیلد‌های کلیدی و غیره ساده است.استفاده از مکانیزم‌های دیگر برای مدیریت داده‌های آن ساده است، مانند SharePoint, Windows Azure Storage Table و دیتابیس‌های NoSQL.تست پذیریASP.NET Identity تست پذیری اپلیکیشن وب شما را بیشتر می‌کند. می‌توانید برای تمام قسمت هایی که از ASP.NET Identity استفاده می‌کنند تست بنویسید.تامین کننده نقش (Role Provider)تامین کننده ای وجود دارد که به شما امکان محدود کردن سطوح دسترسی بر اساس نقوش را می‌دهد. بسادگی می‌توانید نقش‌های جدید مانند &quot;Admin&quot; بسازید و بخش‌های مختلف اپلیکیشن خود را محدود کنید.Claims BasedASP.NET Identity از امکان احراز هویت بر اساس Claims نیز پشتیبانی می‌کند. در این مدل، هویت کاربر بر اساس دسته ای از اختیارات او شناسایی می‌شود. با استفاده از این روش توسعه دهندگان برای تعریف هویت کاربران، آزادی عمل بیشتری نسبت به مدل Roles دارند. مدل نقش‌ها تنها یک مقدار منطقی (bool) است؛ یا عضو یک نقش هستید یا خیر، در حالیکه با استفاده از روش Claims می‌توانید اطلاعات بسیار ریز و دقیقی از هویت کاربر در دست داشته باشید.تامین کنندگان اجتماعیبه راحتی می‌توانید از تامین کنندگان دیگری مانند Microsoft, Facebook, Twitter, Google و غیره استفاده کنید و اطلاعات مربوط به کاربران را در اپلیکیشن خود ذخیره کنید.Windows Azure Active Directoryبرای اطلاعات بیشتر به این لینک مراجعه کنید.یکپارچگی با OWINASP.NET Identity بر اساس OWIN توسعه پیدا کرده است، بنابراین از هر میزبانی که از OWIN پشتیبانی می‌کند می‌توانید استفاده کنید. همچنین هیچ وابستگی ای به System.Web وجود ندارد. ASP.NET Identity یک فریم ورک کامل و مستقل برای OWIN است و می‌تواند در هر اپلیکیشنی که روی OWIN میزبانی شده استفاده شود.ASP.NET Identity از OWIN برای ورود/خروج کاربران در سایت استفاده می‌کند. این بدین معنا است که بجای استفاده از Forms Authentication برای تولید یک کوکی، از OWIN CookieAuthentication استفاده می‌شود.پکیج NuGetASP.NET Identity در قالب یک بسته NuGet توزیع می‌شود. این بسته در قالب پروژه‌های ASP.NET MVC, Web Forms و Web API که با Visual Studio 2013 منتشر شدند گنجانده شده است.توزیع این فریم ورک در قالب یک بسته NuGet این امکان را به تیم ASP.NET می‌دهد تا امکانات جدیدی توسعه دهند، باگ‌ها را برطرف کنند و نتیجه را بصورت چابک به توسعه دهندگان عرضه کنند.انواع هویت سنجی در ASP Core Identityبزار Identity در ASP Core مسئولیت تشخیص هویت و کنترلر دسترسی را به عهده دارد. این ابزار در نسخه های قبل هم وجود داشت اما مانند سایر قسمتها باز نویسی  شده است. در اینجا به سه روش اصلی کنترل دسترسی در Idenity Core می پردازیم.روش Role-Basedدر این روش کاربر بر اساس سمتی که دارد به بخش هایی از سایت دسترسی پیدا می کند. مثلا دسترسی به بخش مدیریت سایت فقط برای کاربرهایی با سمت Admin میسر است. در اینجا ما یک جدول برای نگه داری سمت ها داریم و یک جدول هم برای نگه داری رابطه ی بین کاربران با هر سمت. یک کاربر می تواند چندین سمت داشته باشد.روش Claims-Basedنسخه ی جدید ASP Core تاکید زیادی به استفاده از این روش دارد. در این روش یک کاربر می تواند چند هویت داشته باشد. هر هویت مشخصه های خودش را دارد. دسترسی های یک کاربر بر اساس مشخصه های هر هویت فرق می کند. مثلا شما برای گرفتن وام به بانک مراجعه می کنید و برای شناسایی کارت ملی ارائه می کنید. مشخصات کارت ملی بخشی از مشخصات شما شامل نام و تاریخ تولد را نشان می دهد و یکی از هویت های شما محسوب میشود. حالا اگر بخواهید وام دانشجویی بگیرید باید ثابت کنید دانشجو هستید. در این مرحله کارت دانشجویی ارائه می کنید که شامل نام دانشگاه و شماره ی دانشجویی است. در سیستم Claims-Based انواع مشخصات شما در یک جدول key/value دخیره می شود و بعدا می توانید دسترسی به اکشن ها و کنترلر ها را بر اساس آن محدود کنید.روش Policy-Basedاین شیوه ترکیبی از روشهای قبل است. می توانید برای اجرای هر کدام از اکشنها یک سیاست یا Policy تعریف کنید که می تواند شامل مجموعه از سمت ها و مشخصه های هویتی (Claims)  باشد.علاوه بر اینها چند روش دیگر هم وجود دارد و باید گفت نسخه ی جدید از هر نظر کامل است. به طور کلی پیاده کردن سیستم امنیتی پیچیده است و بهتر است همیشه از Identity استفاده کنید. این سیستم بسیاری از نکات مهم مانند رمز نگاری را به خوبی رعایت کرده است و سطح امنیت سایت را به میزان قابل توجهی بالا می برد.جدول نقش‌های سیستمکار با ارث بری از نگارش جنریک کلاس IdentityRole شروع می‌شود. این کلاس پایه، حاوی تعاریف اصلی فیلدهای جدول نقش‌های سیستم است که اولین آرگومان جنریک آن، نوع کلید اصلی جدول مرتبط را نیز مشخص می‌کند و در اینجا به int تنظیم شده‌است. همچنین یک اینترفیس جدید IAuditableEntity را نیز در انتهای این تعریف‌ها مشاهده می‌کنید. در مورد این اینترفیس و Shadow properties متناظر با آن، در ادامه‌ی بحث با سفارشی سازی DbContext برنامه بیشتر توضیح داده خواهد شد.در اولین بار اجرای برنامه، نقش Admin در این جدول ثبت خواهد شد.جدول کاربران منتسب به نقش‌هاکلاس پایه‌ی جدول کاربران منتسب به نقش‌ها، کلاس جنریک IdentityUserRole است که در اینجا با تغییر آرگومان جنریک آن به int، نوع فیلدهای UserId و RoleId آن به int تنظیم می‌شوند. در کلاس سفارشی سازی شده‌ی فوق، دو خاصیت اضافه‌تر User و Role نیز را مشاهده می‌کنید. مزیت تعریف آن‌ها، دسترسی ساده‌تر به اطلاعات کاربران و نقش‌ها توسط EF Core است.در اولین بار اجرای برنامه، کاربر شماره 1 یا همان Admin به نقش شماره 1 یا همان Admin، انتساب داده می‌شود.جدول جدید  IdentityRoleClaim سیستمدر ASP.NET Core Identity، جدول جدیدی به نام RoleClaim نیز اضافه شده‌است. در این سری از آن برای پیاده سازی سطوح دسترسی پویای به صفحات استفاده خواهیم کرد. ابتدا یک سری نقش ثابت در جدول Roles ثبت خواهند شد. سپس تعدادی کاربر به هر نقش نسبت داده می‌شوند. اکنون می‌توان به هر نقش نیز تعدادی Claim را انتساب داد. برای مثال یک Claim سفارشی که شامل ID سفارشی area:controller:action باشد. به این ترتیب و با بررسی سفارشی آن می‌توان سطوح دسترسی پویا را نیز پیاده سازی کرد و مزیت آن این است که تمام این Claims به صورت خودکار به کوکی شخص نیز اضافه شده و دسترسی به اطلاعات آن بسیار سریع است و نیازی به مراجعه‌ی به بانک اطلاعاتی را ندارد.جدول UserClaim سیستممی‌توان به هر کاربر یک سری Claim مخصوص را نیز انتساب داد. برای مثال مسیر عکس ذخیره شده‌ی او در سرور، چه موردی است و این اطلاعات به صورت خودکار به کوکی او نیز توسط ASP.NET Core Identity اضافه می‌شوند. البته ما در این سری روش دیگری را برای سفارشی سازی Claims عمومی کاربران بکار خواهیم گرفت (با سفارشی سازی کلاس ApplicationClaimsPrincipalFactory آن).جداول توکن و لاگین‌های کاربراندراینجا نیز نحوه‌ی سفارشی سازی و تغییر جداول لاگین‌های کاربران و توکن‌های مرتبط با آن‌ها را مشاهده می‌کنید. این جداول بیشتر جهت دسترسی به حالت‌هایی مانند لاگین با حساب کاربری جی‌میل مورد استفاده قرار می‌گیرند و کاربرد پیش فرضی ندارند (اگر از تامین کننده‌های لاگین خارجی نمی‌خواهید استفاده کنید).جدول کاربران سیستمدر اینجا علاوه بر نحوه‌ی تغییر نوع کلید اصلی جدول کاربران سیستم، نحوه‌ی افزودن خواص اضافه‌تری مانند نام، تاریخ تولد، مکان، تصویر و غیره را نیز مشاهده می‌کنید. به علاوه جدولی نیز جهت ثبت سابقه‌ی کلمات عبور هش شده‌ی کاربران نیز تدارک دیده شده‌است تا کاربران نتوانند از 5 کلمه‌ی عبور اخیر خود (تنظیم NotAllowedPreviouslyUsedPasswords در فایل appsettings.json) استفاده کنند.فیلد IsActive نیز از این جهت اضافه شده‌است تا بجای حذف فیزیکی یک کاربر، بتوان اکانت او را غیرفعال کرد. https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity?view=aspnetcore-6.0&amp;tabs=visual-studio یک پروژه از نوع ASP.NET CORE WEB API ایجاد می کنیمیک اسم برای پروژه انتخاب می کنیمآخرین نسخه NET  رو انتخاب می کنیمدر ابتدای پروژه نسبت به نصب پکیج های به شرح ذیل اقدام می کنیم:Install-Package Microsoft.EntityFrameworkCore -Version 5.0.12Install-Package Microsoft.EntityFrameworkCore.Design -Version 5.0.12Installing NuGet package Microsoft.EntityFrameworkCore.tools 5.0.12Install-Package Microsoft.EntityFrameworkCore.SqlServer -Version 5.0.12Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore -version 5.0.12Install-Package Microsoft.AspNetCore.Identity.UI -Version 5.0.12Install-Package Microsoft.AspNetCore.Authentication.JwtBearer -version 5.0.12وارد فایل Startup شده و در قسمت ConfigureServices کدهای زیر را اضافه می کنیمusing System.Text;
var key = Encoding.ASCII.GetBytes(&amp;quot@#MY_BIG_SECRET_KEY@#&amp;quot);سپس کد زیر را بعد از کد مذکور به شرح ذیل اضافه می کنیمusing Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
 services.AddAuthentication(options =&gt;
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; ;
            }).AddJwtBearer(options =&gt;
            {
                options.Events = new JwtBearerEvents
                {
                    OnTokenValidated = context =&gt;
                    {
                       //TODO CODE
                        return Task.CompletedTask;
                    }
                };
                options.RequireHttpsMetadata = false;
                options.SaveToken = true;
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(key),
                    ValidateIssuer = false,
                    ValidateAudience = false
                };
            });
سپس یک احزار هویت به پروژه اضافه می کنیم app.UseAuthentication();یک کنترلر به پروژه به اسم SecurityController از نوع web api empty به پروژه اضافه می کنیم:using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
namespace SecurityWebApi.Controllers

{
    [Route(&amp;quotapi/[controller]&amp;quot)]
    [ApiController]
    [Authorize]
    public class SecurityController : ControllerBase
    {
        [HttpGet(&amp;quotgetFruits&amp;quot)]
        [AllowAnonymous]
        public ActionResult GetFruits()
        {
            List&lt;string&gt; mylist = new List&lt;string&gt;() { &amp;quotapples&amp;quot, &amp;quotbannanas&amp;quot };
            return Ok(mylist);
        }
        [HttpGet(&amp;quotgetFruitsAuthenticated&amp;quot)]
        public ActionResult GetFruitsAuthenticated()
        {
            List&lt;string&gt; mylist = new List&lt;string&gt;() { &amp;quotorganic apples&amp;quot, &amp;quotorganic bannanas&amp;quot };
            return Ok(mylist);
        }
    }
}پروژه رو اجرا می کنیم :چون روی کنترلر  [Authorize] اعمال شده است لذا چون احرازهویت نشده است پیغام Error: Unauthorized می دهیدیک پوشه Models به پروژه اضافه می کنیم و یک کلاس فایل MyLoginModelType به پروژه اضافه می کنیم:namespace SecurityWebApi.Models
{
    public class MyLoginModelType
    {
        public string Email { get; set; }
        public string Password { get; set; }
    }
}در این قسمت متد مربوط به ساختن توکن را ایجاد می کنیم توجه شود چون تا اینجای پروژ هنوز Identity به پروژه اضافه نشده است قسمت بررسی ایمیل و رمز عبور بصورت هارد کد پیاده سازی شده است. 
        [AllowAnonymous]
        [HttpPost(&amp;quotgetToken&amp;quot)]
        public async Task&lt;ActionResult&gt; GetToken([FromBody] MyLoginModelType  myLoginModelType)
        {
           if(myLoginModelType.Email==&amp;quotjavad.jahangiri.niopdc@gamil.com&amp;quot &amp;&amp;myLoginModelType.Password==&amp;quotPa$$w0rd&amp;quot)
            { 
                    var tokenHandler = new JwtSecurityTokenHandler();
                    var key = Encoding.ASCII.GetBytes(&amp;quot@#MY_BIG_SECRET_KEY@#&amp;quot);
                    var tokenDescription = new SecurityTokenDescriptor
                    {
                        Subject = new ClaimsIdentity(new Claim[]
                        {
                        new Claim(ClaimTypes.Name, myLoginModelType.Email)
                        }   
                    ),
                        Expires = DateTime.UtcNow.AddDays(1),
                        SigningCredentials = new SigningCredentials(new
SymmetricSecurityKey(key),SecurityAlgorithms.HmacSha256Signature),
                    };
                    var token = tokenHandler.CreateToken(tokenDescription);
                    var tokenString = tokenHandler.WriteToken(token);
                    return Ok(new { token = tokenString });
                }
                else
                {
                    return Ok(&amp;quotfailed , try again&amp;quot);
                }
        }

در اینجا کاربر با ارسال ایمیل و رمز عبوردر صورت صحیح بودن اطلاعات برای ان توکن ساخته و ارسال می شوددر این قسمت نحوه ارسال توکن در هدر درخواست از طریق نرم افزار postman نمایش داده شده:در این مرحله اضافه کردن کنترلر Identitiy به پروژه به شرح ذیل می باشددر ادامه یک DataContext برای ارتباط Identity با دیتابیس sqlserver ایجادمیشوددر این قسمت کلاس سفارشی کاربر برای Identity ایجاد می شودحال Identity به شرح ذیل به پروژه اضافه می شود:بعد از اضافه شدن کنترلر Identity جمله اتصال را عوض می کنیمبعد نسبت به ایجاد مایگریشن و بروزرسانی دیتابیس عمل می کنیم:Add-Migration createIdentitySchemaUpdate-Databaseهمانگونه که مشاهده می کنید دیتابیس به شرح زیر ساخته می شود:به فایل Startup بر می گردیم :کدهای زیر را به ان اضافه می کنیم  var userMachine = context.HttpContext.RequestServices.GetRequiredService&lt;UserManager&lt;SecurityWebApiUser&gt;&gt;();
                        var user = userMachine.GetUserAsync(context.HttpContext.User);
                        if (user == null)        
                    context.Fail(&amp;quotUnAuthorized&amp;quot);مسیر دسترسی به فایل  SecurityWebApiUser مسیر SecurityWebApi.Areas.Identity.Data می باشدحالا به کنترلر Securtiy بر می گردیم و ایتم های زیر را به پروژه اینجکت می کنیم       private readonly SecurityWebApiContext _dbContext;
        private readonly UserManager&lt;SecurityWebApiUser&gt; _userManager;
        private readonly SignInManager&lt;SecurityWebApiUser&gt; _signInManager;
        public SecurityController(SecurityWebApiContext dbContext, UserManager&lt;SecurityWebApiUser&gt; userManager, SignInManager&lt;SecurityWebApiUser&gt; signInManager)
        {
            _dbContext = dbContext;
            _userManager = userManager;
            _signInManager = signInManager;
        }و در نهایت تابع دریافت توکن و ثبت نام را به شرح ذیل در پروژه تغییر می دهیم که بتوانیم با کمک Identityیک کاربر را در دیتابیس ایجاد کنیم از طریق ان لاگین نموده و توکن را دریافت کنیم  [AllowAnonymous]
        [HttpPost(&amp;quotgetToken&amp;quot)]
        public async Task&lt;ActionResult&gt; GetToken([FromBody] MyLoginModelType myLoginModelType)
        {
            var user = _dbContext.Users.FirstOrDefault(x =&gt; x.Email == myLoginModelType.Email);
            if (user != null)
            {
                var singInResult = await _signInManager.CheckPasswordSignInAsync(user, myLoginModelType.Password, false);
                if (singInResult.Succeeded)
                {
                    var tokenHandler = new JwtSecurityTokenHandler();
                 var key = Encoding.ASCII.GetBytes(&amp;quot@#MY_BIG_SECRET_KEY@#&amp;quot);
                    var tokenDescription = new SecurityTokenDescriptor
                    {
                        Subject = new ClaimsIdentity(new Claim[]                      {
                        new Claim(ClaimTypes.Name, myLoginModelType.Email)
                        }
                       ),
                        Expires = DateTime.UtcNow.AddDays(1),
                        SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature),
                    };
                    var token = tokenHandler.CreateToken(tokenDescription);
                    var tokenString = tokenHandler.WriteToken(token);
                    return Ok(new { token = tokenString });
                }
                else
                {
                    return Ok(&amp;quotfailed , try again&amp;quot);
                }
            }
            return Ok(&amp;quotfailed , try again&amp;quot);
        }

       [AllowAnonymous]
        [HttpPost(&amp;quotregister&amp;quot)]
        public async Task&lt;IActionResult&gt; Register([FromBody] MyLoginModelType myLoginModelType)
        {
            SecurityWebApiUser securingWebApiDotNetCoreWithIdentity = new SecurityWebApiUser()
            {
                Email = myLoginModelType.Email,
                UserName = myLoginModelType.Email,
                EmailConfirmed = false,
            };

            var result = await _userManager.CreateAsync(securingWebApiDotNetCoreWithIdentity, myLoginModelType.Password);
            if (result.Succeeded)
            {
                return Ok(new { result = &amp;quotRegister Success&amp;quot });
            }
            else
            {
                StringBuilder sb = new StringBuilder();
                foreach (var error in result.Errors)
                {
                    sb.Append(error.Description);
                }
                return Ok(new { Result = $&amp;quotRegister Fail: {sb.ToString()}&amp;quot });
            }
        }
 در تصویر زیر مشاهده می کنیم که یک کاربر در دیتابیس ایجاد می شود نکته :دقت شود بصورت پیش فرض در Identity در قسمت SignIn گزینه RequireConfirmedAccount فعال می باشد باید انرا غیرفعال کنیم در نهایت حالا می تواند همانند توضیحات قبلی با این کاربر درخواست یک توکن داده و از طریق این توکن webapi مورد نظر خود را احراز هویت نمایید.برای دانلود سورس پروژه از گیت هاب بنده استفاده کنید https://github.com/javadjahangiriniopdc/SecuringWebApiDotNetCoreWithIdentityAndJwt  https://www.aparat.com/javadjahangiriniopdc با تشکر از مطالعه این مقاله ,مثل همیشه کنجکاو باشید!!!در دوره های آموزش تضمینی مجتمع فنی ارومیه که به صورت خصوصی و عمومی در دو شیوه حضوری و آنلاین برگزار می شود سرفصل های بسیار متنوع و کاربردی را بصورت پروژه محور آموزش داده می شود تا شخص کارآموز بتواند بلافاصله پس از اتمام این دوره در کمترین زمان ممکن وارد بازار کار شود.آموزش تخصص ماست با ما حرفه ای شویدجهت مشاوره با شماره 09149431772 در ارتباط باشید ...</description>
                <category>جواد جهانگیری</category>
                <author>جواد جهانگیری</author>
                <pubDate>Sat, 04 Dec 2021 20:48:10 +0330</pubDate>
            </item>
                    <item>
                <title>الگوی UnitOfWork pattern در C# asp.net core</title>
                <link>https://virgool.io/@javadjahangiri/%D8%A7%D9%84%DA%AF%D9%88%DB%8C-unitofwork-pattern-%D8%AF%D8%B1-c-aspnet-core-hobqvq07tl6v</link>
                <description>به نام آن که جان را فکرت آموخت / چراغ دل به نور جان برافروختبا عرض سلام و وقت بخیر خدمت کاربران محترم سایت ویرگول، در این مقاله آموزشی به موضوع نحوه ساخت و استفاده از الگوی Repository و Generic Repository به همراه Unit Of Work پرداخته می شود و سعی شده یک آموزش کاربردی و پروژه محور از بحث Unit Of Work ارایه گردد.ایده این سری مقاله های آموزشی از این موضوع سرچشمه می گیرد که بخشی از خوانندگان وجود دارد که به محتوای نوشتاری آنلاین بهتر پاسخ می دهند و ترجیج می دهند مهارت های جدید را به سرعت از طریق خواندن افزایش دهند.این سری اموزش ها با ارایه پکیج آموزش های کاربردی در خصوص C# asp.net core آغاز می شود که انتظار می رود با واکنش مثبت کاربران همراه شود. https://www.aparat.com/javadjahangiriniopdc/playlists توجه: این مقاله به مرور زمان، ویرایش و یا تکمیل می‌شود!تقاضا: در صورتی که با مشکل تایپی، دستوری و یا مفهومی در این مقاله برخورد کردید، از شما دوست عزیز و گرامی، صمیمانه تقاضا می‌کنم که اینجانب را مطلع کرده، تا نسبت به تصحیح و یا تکمیل آن، در اسرع وقت، اقدام نمایم.با کمال تشکرجواد جهانگیری شماره تلفن همراه: 09149431772نشانی پست الکترونیکی: javad.jahangiri.niopdc@gmail.comفیلم‌های آموزشی در آپارات:جواد جهانگیری (CTO) - آپاراتفیلم آموزشی در یوتویب: javad jahangiri - YouTubeنسخه مقاله: ۱.۱ - تاریخ بروزرسانی: 1400/09/09فرض کنید وقتی یک درخواست به روی سرور ارسال می شود باعنایت اینکه چندین کلاس و یا تابع برای پاسخ به این درخواست فراخوانی شود و از سوی دیگر ممکن است از هر کدام از انها به DbContext و داده های خود نیاز داشته باشد ،بعبارتی یک درخواست برای اجرا نیاز به چندین نمونه از DbContext  را نیاز داشته باشد ما باید کاری کنیم و مکانیزمی تعریف کنیم که در یک Request  فقط و فقط یک نمونه از DbContext ایجاد شود.این به این مفهوم نیست که ما یک کانکشن برای کل برنامه Application ایجاد کنیم (SingleTone) این کار درستی نیست بلکه ما می خواهیم به ازای Per Request فقط یک نمونه ازDbContext  را داشته باشیمتوجه:در برنامه های ویندوز فرم دانت ما حالت Stateful را داریم و کانکشن تو حافظه کاربر ایجاد می شود و مشکلی ندارد به ازای کل Application ما یک کانکشن داشته باشیم و حتی Performance را نیز افزایش می دهد ولی برنامه های وب بصورت Stateless می باشد و بعد از این که یک درخواست اجرا می شود کل اطلاعات از روی سرور حذف می شود اگر به ازای کل برنامه یک کانکشن داشته باشیم یعنی Singleton به ازای Application باشد با ورود اولین کاربر یک کانکشن ایجاد می شود و با بیرون رفتن کاربر این کانکشن بسته شده و تمامی درخواست های سایر کاربران با خطا مواجه می شود پس باید کاری کنیم که به ازای هر درخواست حالت Singleton را داشته باشیم توجه شود Unit of Work (UOW)بصورت توکار در داخل Entity Framework موجود استUnit of Work به معنای واحد کار است و یک نوع الگوی طراحی است. بر اساس این الگو نباید در هر قسمت از برنامه شئ ای از روی DbContext بسازیم و فقط یک بار باید از روی DbContext شی جدید ساخت. به عبارت دیگر برنامه نویس در لایه ی Business Logic نباید با Repository های مختلف کار کند و این وظایف باید به Unit of Work سپرده شود و برنامه نویس فقط از آن استفاده کند. می توان از Unit of Work به عنوان یک Facade از Repository ها یاد کرد.طبق این الگو، تمام درخواست های کار با دیتابیس در یک صف قرار می گیرند و پشت سر هم انجام می شوند. بعد از آنکه تمام این درخواست ها با موفقیت اجرا شدند، دستور SaveChanges اجرا می شود. چون این الگوی طراحی از مفهوم Transaction استفاده می کند، اگر در این بین مشکلی پیش بیاید یا یکی از درخواست ها با خطا مواجه شود تمام درخواست ها لغو می شوند و هیچ تغییری در دیتابیس رخ نخواهد داد و در اصطلاح Rollback اتفاق می افتد.این روش مزیت های بسیاری دارد، مثلا Connection های کمتری به دیتابیس وجود خواهند داشت چون در Unit of Work یک تراکنش به ازای چند عمل وجود دارد و نه یک تراکنش به ازای هر عمل.چرا Unit Of Work ؟عدم دسترسی مستقیم Controller به دیتابیس هنگام عملیات CRUD. چون ارتباط، با استفاده از کلاس و اینترفیس مربوط به Unit Of Work برقرار می شود.افزایش امنیت دیتابیسبهینگی سیستم و جلوگیری از خطاهای بالقوه دیتابیسی( اگر درخواستی نیاز به چندین بار ارتباط با دیتابیس داشته باشد، در هر ارتباط یک نمونه از دیتابیس در سرور ساخته می شود که اگر تعداد درخواست ها بالا باشد سرعت دیتابیس و سرور کند می شود.)طبق اموزش های ارایه شده در سایت مایکروسافت یه پروژه ASP.NET Core MVC به شرح ذیل ایجاد می کنیم: https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/start-mvc?view=aspnetcore-5.0&amp;tabs=visual-studio یک پروژه از نوع C# asp.net Core Web App (Model-View-Controller) ایجاد می کنیمیک نام دلخواه برای پروژه خود انتخاب کنید:فریم ورک مورد نظر را انتخاب می کنیم در حال حاضر نسخه 6 مورد استفاده قرار می گیرددر نهایت یک پروژه به شرح ذیل ایجاد می شودابتدا نسبت به نصب پکیج های مطابق شکل زیر اقدام می کنیم Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.Design
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Toolsیک Entity بنام Student  به پروژه اضافه می کنید:namespace UnitOfWorkWebApp.Models
{
    public class Student
    {
        public int  Id { get; set; }
        public string Name { get; set; }
    }
}ودر ادامه یک پوشه به پروژه  infrastructure اضافه کرده ویک اینترفیس بنام IStudentRepo به شرح ذیل به پروژه اضافه می کنیم :using UnitOfWorkWebApp.Models;
namespace UnitOfWorkWebApp.infrastructure
{
    public interface IStudentRepo
    {
        IList&lt;Student&gt; GetAll();
        Student GetById(int id);
        void Insert(Student student);
        void Update(Student student);
        void Delete(Student student);
    }
}یک پوشه Data به پروژه اضافه کرده و یک کلاس تحت عنوان Context به پروژه اضافه می کنیم:using Microsoft.EntityFrameworkCore;
using UnitOfWorkWebApp.Models;
namespace UnitOfWorkWebApp.Data
{
    public class Context : DbContext
    {
        public Context(DbContextOptions options) : base(options)
        {
        }
        public DbSet&lt;Student&gt; Students { get; set; }
    }
}یک پوشه هم بنام Services به پروژه اضافه کنید و یک کلاس بنام StudentRepo به این پوشه اضافه کنیدusing UnitOfWorkWebApp.Data;
using UnitOfWorkWebApp.infrastructure;
using UnitOfWorkWebApp.Models;
namespace UnitOfWorkWebApp.Services
{
    public class StudentRepo : IStudentRepo
    {
        private Context _context;
        public StudentRepo(Context context)
        {
            _context = context;
        }
        public void Delete(Student student)
        {
            _context.Students.Remove(student);
        }
        public IList&lt;Student&gt; GetAll()
        {
            return _context.Students.ToList();
        }
        public Student GetById(int id)
        {
            var student = _context.Students.Where(x =&gt; x.Id == id).FirstOrDefault();
            return student;
        }
        public void Insert(Student student)
        {
          _context.Students.Add(student);
        }
    public void Update(Student student)
        {
            _context.Students.Update(student);      
        }
    }
}به پوشه infrastructure یک اینترفیس IUnitOfWork اضافه می کنیم:namespace UnitOfWorkWebApp.infrastructure
{
    public interface IUnitOfWork
    {
        IStudentRepo StudentRepo { get; }
        void Save();
    }
}کلاس UnitOfWork به پوشه سرویس بصورت زیر اضافه می کنیم:using UnitOfWorkWebApp.Data;
using UnitOfWorkWebApp.infrastructure;
namespace UnitOfWorkWebApp.Services
{
    public class UnitOfWork : IUnitOfWork
    {
        private Context _context;
        private IStudentRepo _studentRepo;
        public UnitOfWork(Context context)
        {
            _context = context;
        }
        public IStudentRepo StudentRepo
        {
            get
            {
                return _studentRepo=_studentRepo ?? new StudentRepo(_context);
            }
        }
public void Save()
        {
            _context.SaveChanges(); 
        }
    }
}یک ConnectionStrings به فایل appsettings.json اضافه می کنیم:{ 
 &amp;quotConnectionStrings&amp;quot: {
    &amp;quotDefaultConnection&amp;quot: &amp;quotServer=.;Database=UnitOfWork;Trusted_Connection=True;MultipleActiveResultSet=True&amp;quot
  },
  &amp;quotLogging&amp;quot: {
    &amp;quotLogLevel&amp;quot: {
      &amp;quotDefault&amp;quot: &amp;quotInformation&amp;quot,
      &amp;quotMicrosoft.AspNetCore&amp;quot: &amp;quotWarning&amp;quot
    }
  },
  &amp;quotAllowedHosts&amp;quot: &amp;quot*&amp;quot
}همانگونه که در مستندات مایکروسافت هم ذکر شده است در نسخه دانت کور6 فایل startup حذف شده و باید کارهای مربوط به سرویس ها و تزریق وابستگی ها و MiddleWare را باید در فایل Program در قسمت مربوطه انجام داد builder.Services.AddDbContext&lt;Context&gt;(options =&gt;
    options.UseSqlServer(builder.Configuration.GetConnectionString(&amp;quotDefaultConnection&amp;quot)));

builder.Services.AddTransient&lt;IUnitOfWork, UnitOfWork&gt;();در ادامه یک مایگریشن برای پروژه به شرح زیر ایجاد می کنیم: Add-Migration first
update-databaseساختار پروژه تا اینجای مقاله به شرح زیر می باشدو دیتابیس بصورت زیر ساخته می شودبصورت زیر توسط تابع سازنده unitofwork را به داخل کنترلر Home تزریق می کنیم:حالا بصورت زیر می توانیم از UnitOfWork در کنترلر استفاده کنیم با تشکر از مطالعه این مقاله ,مثل همیشه کنجکاو باشید!!!در دوره های آموزش تضمینی مجتمع فنی ارومیه که به صورت خصوصی و عمومی در دو شیوه حضوری و آنلاین برگزار می شود سرفصل های بسیار متنوع و کاربردی را بصورت پروژه محور آموزش داده می شود تا شخص کارآموز بتواند بلافاصله پس از اتمام این دوره در کمترین زمان ممکن وارد بازار کار شود.آموزش تخصص ماست با ما حرفه ای شویدجهت مشاوره با شماره 09149431772 در ارتباط باشید ... https://www.aparat.com/javadjahangiriniopdc/playlists </description>
                <category>جواد جهانگیری</category>
                <author>جواد جهانگیری</author>
                <pubDate>Sun, 28 Nov 2021 10:48:05 +0330</pubDate>
            </item>
                    <item>
                <title>آموزش Repository Pattern  در C# asp.net core</title>
                <link>https://virgool.io/@javadjahangiri/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-repository-pattern-%D8%AF%D8%B1-c-aspnet-core-iawhvlijicnh</link>
                <description>به نام آن که جان را فکرت آموخت / چراغ دل به نور جان برافروختبا عرض سلام و وقت بخیر خدمت کاربران محترم سایت ویرگول، در این مقاله آموزشی به موضوع نحوه ساخت و استفاده از الگوی Repository و Generic Repository به همراه Unit Of Work پرداخته می شود و سعی شده یک آموزش کاربردی و پروژه محور از بحث Repository  ارایه گردد.ایده این سری مقاله های آموزشی از این موضوع سرچشمه می گیرد که بخشی از خوانندگان وجود دارد که به محتوای نوشتاری آنلاین بهتر پاسخ می دهند و ترجیج می دهند مهارت های جدید را به سرعت از طریق خواندن افزایش دهند.این سری اموزش ها با ارایه پکیج آموزش های کاربردی در خصوص C# asp.net core  آغاز می شود که انتظار می رود با واکنش مثبت کاربران همراه شود.توجه: این مقاله به مرور زمان، ویرایش و یا تکمیل می‌شود! تقاضا: در صورتی که با مشکل تایپی، دستوری و یا مفهومی در این مقاله برخورد کردید، از شما دوست عزیز و گرامی، صمیمانه تقاضا می‌کنم که اینجانب را مطلع کرده، تا نسبت به تصحیح و یا تکمیل آن، در اسرع وقت، اقدام نمایم. با کمال تشکر جواد جهانگیری  شماره تلفن همراه: 09149431772 نشانی پست الکترونیکی: javad.jahangiri.niopdc@gmail.com فیلم‌های آموزشی در آپارات:جواد جهانگیری (CTO) - آپاراتفیلم آموزشی در یوتویب: javad jahangiri - YouTubeنسخه مقاله: ۱.۱ - تاریخ بروزرسانی: 1400/09/09در حقیقت Repository ها بر روی کالکشنی از داده ها کار می کند که تمامی عملیات CRUD و جستجو و فیلتر کردن داده ها را برای ان پیاده سازی می کند و هر کسی بخواهد با ان کالکشن اطلاعات کار کند در حقیقت این Repository بعنوان یک واسط می شود که با آن کار کند معمولا برای EF Core از Pattern مربوط به Repository استفاده می کنند که از مزایا این روش در کدنویسی می توان به : durabilitypersistent cleanQualityاشاره کرد در اینجا می خواهم به یک نکته مهم اشاره کنم که Service با Repository چه تفاوتی دارد سرویس درحقیقت منطق برنامه (logic) برنامه را پیداسازی می کند اما Repository بر روی کالکشن ای از داده کار می کند سرویس می تواند در دل خودش از چندتا Repository و یا Service دیگر استفاده کند اما Repository فقط بر روی یک کالکشن ای  داده کار می کند برای توضیح این موضوع یک پروژه از نوع C# asp.net core web app (Mode-View-Controller) ایجاد می کنیم یک اسم دلخواه به پروژه می دهیمپروژه رو بر روی فریم ورک دانت کور 5 تنظیم می کنیم در نهایت یک پروژه به شرح ذیل ایجاد می کنیمیک Model بنام MyModel به شرح ذیل ایجاد می کنیم که دارای دو property به شرح ذیل می باشد:دو پوشه بنام های Repositories و IRepositories به پروژه اضافه می کنیم و در پوشه IRepositories یک این Interface به شرح ذیل ایجاد می کنیم:سپس یک کلاس MyModelRepository در پوشه Repositories ایجاد می کنیم که اینترفیس IMyModelRepository را پیاده سازی کند:خوب حالا نوبت به تزریق سرویس های می رسد وارد فایل Startup پروژه شده و در قسمت تنظیمات سرویس های کدها زیر را اضافه می کنیمحالا اگر در هر جای پروژه به ابجکتی از نوع MyModelRepository نیاز باشد توسط دانت کور ساخته و تحویل کلاسی که به ان وابستگی دارد می شود وارد کنترلر برنامه شده و سرویس های در تابع سازنده به شرح ذیل تزریق می کنیمو در نهایت در اکشن index بصورت ذیل سرویس را فراخوانی می کنیم برای دریافت سورس پروژه می توانید از طریق گیت های بنده اقدام کنید https://github.com/javadjahangiriniopdc/RepositoryPatternWebApp با تشکر از مطالعه این مقاله ، مثل همیشه کنجکاو باشید !!!در دوره های آموزش تضمینی مجتمع فنی ارومیه که به صورت خصوصی و عمومی در دو شیوه حضوری و آنلاین برگزار می شود سرفصل های بسیار متنوع و کاربردی را بصورت پروژه محور آموزش داده می شود تا شخص کارآموز بتواند بلافاصله پس از اتمام این دوره در کمترین زمان ممکن وارد بازار کار شود.آموزش تخصص ماست با ما حرفه ای شویدجهت مشاوره با شماره 09149431772 در ارتباط باشید ... https://www.aparat.com/javadjahangiriniopdc/playlists </description>
                <category>جواد جهانگیری</category>
                <author>جواد جهانگیری</author>
                <pubDate>Sat, 27 Nov 2021 22:44:05 +0330</pubDate>
            </item>
                    <item>
                <title>آموزش تزریق وابستگی DependencyInjectionیا(DI) در  C# asp.net core</title>
                <link>https://virgool.io/@javadjahangiri/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-dependencyinjection%DB%8C%D8%A7di-%D8%AF%D8%B1-c-aspnet-core-bkycn3f7apni</link>
                <description>به نام آن که جان را فکرت آموخت / چراغ دل به نور جان برافروختبا عرض سلام و وقت بخیر خدمت کاربران محترم سایت ویرگول، در این مقاله آموزشی به موضوع DependencyInjectionیا(DI) در  C# asp.net core پرداخته می شود و سعی شده یک آموزش کاربردی و پروژه محور از بحث تزریق وابستگی ها ارایه گردد.ایده این سری مقاله های آموزشی از این موضوع سرچشمه می گیرد که بخشی از خوانندگان وجود دارد که به محتوای نوشتاری آنلاین بهتر پاسخ می دهند و ترجیج می دهند مهارت های جدید را به سرعت از طریق خواندن افزایش دهند.این سری اموزش ها با ارایه پکیج آموزشی کاربردی در خصوص C# asp.net core  آغاز می شود که انتظار می رود با واکنش مثبت کاربران همراه شود.توجه: این مقاله به مرور زمان، ویرایش و یا تکمیل می‌شود! تقاضا: در صورتی که با مشکل تایپی، دستوری و یا مفهومی در این مقاله برخورد کردید، از شما دوست عزیز و گرامی، صمیمانه تقاضا می‌کنم که اینجانب را مطلع کرده، تا نسبت به تصحیح و یا تکمیل آن، در اسرع وقت، اقدام نمایم. با کمال تشکر جواد جهانگیری  شماره تلفن همراه: 09149431772 نشانی پست الکترونیکی: javad.jahangiri.niopdc@gmail.com فیلم‌های آموزشی در آپارات:جواد جهانگیری (CTO) - آپاراتفیلم آموزشی در یوتویب: javad jahangiri - YouTubeنسخه مقاله: ۱.۱ - تاریخ بروزرسانی: 1400/09/09شما فرض کنید کلاسی داریم که تسک خاصی را انجام می دهد و برای انجام این کار به کلاس های دیگری نیاز دارد و به تسک دیگری نیاز دارد در حقیقت نیاز به یک ابجکت از یک کلاس دیگر دارد در این حالت در جای که به ان نیاز داریم بجای اینکه از این ابجکت new کنیم در این حالت این ابجکت را Inject می کنیم یا بعبارتی انرا تزریق می کنیم یا بعبارت دیگر ان سرویس ها را برای ان تامین می کنیم که بتونه کار ما را انجام دهد https://www.aparat.com/javadjahangiriniopdc/playlists ما برای تزریق وابستگی ها سه حالت داریم :از طریق تابع سازنده که بهترین روش می باشداز طریق propertyاز طریق متد methodیک پروژه از نوع asp.net core web app (model-view-controller) ایجاد می کنیم :یک نام دلخواه به پروژه می دهیم تراگت فریم ورک بر روی .NET5.0 قرار می دهیمدر نهایت پروژه نمونه ای به شرح ذیل ساخته می شود:دو پوشه بنام های IServices و Services به پروژه اضافه می کنیمو در داخل پوشه IServices  یک اینترفیس بنام ISampleService ایجاد می کنیم که دارای یک تابع بنام SampleFunction می باشدسپس یک سرویس بنام SampleService را نیز به پوشه Services اضافه می کنیم که اینترفیس ISampleService را پیاده سازی می کنددر ادامه یک اینترفیس دیگر بنام IMyService در پوشه اینترفیس سرویس ها ایجاد می کنیم که دارای یک تابع بنام MyFunction می باشد که این تابع برای محاسبات خود به SampleFunction نیاز داردو در ادامه یک سرویس نیز بنام MyService ایجاد می کنیم که اینترفیس IMyService  را پیاده سازی می کندتوجه داشته باشید که MyService  برای انجام عملیات محاسبات خود به SampleService به شکل زیر نیاز دارد تقریبا منطق انجام کار به شرح ذیل خواهد بود:حالا فرض کنید ما می خواهیم در کنترلر از این سرویس MyService به شرح ذیل استفاده کنیم:هرکار انجام بدهیم با خطا مواجه خواهیم شد زیرا MyService برای اجرا نیاز به SampleService را دارد ما می توانیم چندتا کار انجام بدهیم روش اول :propertyبه داخل MyService رفته و آبجکت SampleService  را به public تغییر داده و در کنترلر آن را با ابجکت جدید مقدار دهی می کنیم و اگر کاربر فراموش کند که SampleService  را با یک ابجکت جدید مقدار دهی کند برنامه دچار خطا می شودروش دوم : با استفاده از متد (یک واسط )در این روش یک متد می نویسیم که وظیفه ایجاد و تخصیص ابجکت را بر عهده بگیرد و در داخل کنترلر ان را فراخوانی و یک ابجکت جدید SampleService  را به ان پاس می کنیم و این روش نیز جالب نیست و اگر کار فراموش کند که متد را فراخوانی کند برنامه با خطا مواجه می شودروش سوم :تابع سازنده که بهترین روش می باشد و اکثر IOC Container آن را پشتیبانی می کنند در این روش یک تابع سازنده ساخته شده و ابجکت مورد نیاز از طریق سازنده به داخل کلاس تزریق می شود. خوبی این روش این است که هنگام که برنامه نویس می خواهد از سرویس یک ابجکت ایجاد کند مجبورا باید نیازمندی های را نیز برای تابع سازنده ساخته و ارسال نماییداما در عمل و واقعیت ما نمی خواهیم خودمان این کار را انجام دهیم و در واقع می خواهیم یک نفر دیگر این کار را برای ما انجام دهد یعنی بعبارتی سرویس ما نیازمندهای خودش را به ان اعلام نمایید و ان چیز قبل از ایجاد ابجکت این نیازمندهای را برای ان ایجاد و به ان پاس نمایید که این کار IOC Container مثل ninject انجام می دهد که در دانت کور بصورت توکار (Build in) وجود دارد.برای این کار در دانت کور InjectService (تزریق سرویس ها) را انجام بدهیم به سه روش ذیل عمل کنیم:روش اول:AddScopedروش دوم:AddSingletonروش سوم:AddTransientکه برای این کار وارد فایل Startup.Cs شده و به تابع ConfigureServices می رویم و برای نمایش هر سه تا حالت در زیر من هر سه تا حالت را می نویسم بعد هر کدوم را مرحله به مرحله توضیح می دهمروش AddSingleton:در این روش یک نمونه برای همه Request در برنامه ساخته  می شود یعنی برای اولین درخواست یک نمونه ایجاد می شود و برای بقیه درخواست از این نمونه استفاده می شود نکته:باعنایت به اینکه برنامه های وب بصورت Stateless می باشد بعد از اجرای درخواست حافظه ازاد می شود در صورت استفاده از این روش باید دقت شود که با اتمام درخواست این نمونه در برنامه از بین می رود و دیگر نمونه ای ساخته نمی شود برای مثال برنامه نویس های اماتور فکر می کنند که موقعی یک کانکشن به دیتابیس ایجاد می شود همانند برنامه های ویندوز فرم می بایستی در برنامه وب نیز به این شکل باشد که یک اشتباه بزرگ است زیرا با ورود اولین کاربر کانکشن ایجاد می شود و با خروج اولین کار کانکشن بسته شد و بقیه کاربران با خطا مواجه می شوند که بهتر است کانکشن بصورت Per Request  باشد یعنی به ازای هر درخواست یک کانکشن ایجاد شود نه به اجزای کل برنامه یک کانکشن به دیتابیس داشته باشیم و همچنین نباید اجازه بدهیم که به ازای یک درخواست بیش از یک کانکشن باز شودروش AddScope:به ازای هر درخواست برای هر کلاسی یک نمونه از اون ابجکت بساز  برای مثال فرض کنید در یک درخواست ما نیاز است ده تا از یک ابجکت ساخته شود فقط یک نمونه از این ابجکت ایجاد شد و برای بقیه استفاده می شودروش AddTransient:به ازای هر درخواست برای هر کلاس در صورت نیاز از این ابجکت به ازای هر بار نیاز یک نمونه ایجاد می شود برای مثال فرض کنید در یک درخواست در ده جا نیاز به ایجاد ابجکت هست پس ده تا از این ابجکت new می شودبصورت خلاصه روش AddScope و AddTransient بصورت Per Request هست در روش AddScope  به ازای هر درخواست یک نمونه ایجاد می شود ولی در روش AddTransient  به ازای هر Request در صورت نیاز چندین نمونه ساخته می شود ولی روش AddSingleton به ازای همه درخواست Application فقط یک نمونه ساخته می شود بعبارت دیگر می توان گفت که AddScope در حقیقت AddSingleton به ازای هر درخواست می باشدحالا برای درک بهتر ما هر دو سرویس که در این مقاله ایجاد کردیم به روش AddScope به پروژه اضافه می کنیموارد کنترلر شده و بصورت تابع سازنده سرویس را تزریق می کنیم و در داخل MyService نیز به شکل زیر باز از طریق تابع سازنده تزریق وابستگی می کنیمتوجه شود برای کش شدن آبجکت ها و افزایش پرفورمانس حتما ابجکت های از نوع Readonly تعریف کنیدحالا برمی گردیم به کنترل و لطفا به  نحوه فراخوانی سرویس دقت کینددر Action مربوط به index ما نیاز به یک myservice داریم چون در ConfigureServices تعریف کردیم یک نمونه از ان بصورت اتوماتیک ایجاد می شود در هنگام ایجاد myservice دقت کنید نیاز به سرویس sampleService  می باشد که با توجه به اینکه ConfigureServices تعریف کردیم یک نمونه از ان ایجاد شده و تحویل myservice  شده و سپس یک نمونه از myservice  ایجاد می شود بعبارتی ما در این حالت نیازمند ایجاد نمونه نمی باشیم و خود دانت کور وظیفه ایجاد نمونه با توجه به وابستگی ها را بر عهده می گیرد.سورس پروژه را می تونید از روی گیت هات بنده دانلود کنید https://github.com/javadjahangiriniopdc/DependencyInjectionWebApp باتشکر از مطالعه این مقاله,مثل همیشه کنجکاوباشید!!!در دوره های آموزش  تضمینی مجتمع فنی ارومیه که به صورت خصوصی و عمومی در دو شیوه حضوری و آنلاین برگزار می شود سرفصل های بسیار متنوع و کاربردی را بصورت پروژه محور آموزش داده می شود تا شخص کارآموز بتواند بلافاصله پس از اتمام این دوره در کمترین زمان ممکن وارد بازار کار شود.آموزش تخصص ماست با ما حرفه ای شویدجهت مشاوره با شماره 09149431772 در ارتباط باشید ... https://www.aparat.com/javadjahangiriniopdc/playlists </description>
                <category>جواد جهانگیری</category>
                <author>جواد جهانگیری</author>
                <pubDate>Sat, 27 Nov 2021 10:47:29 +0330</pubDate>
            </item>
                    <item>
                <title>آموزش دیتابیس ردیس Redis Tutorial</title>
                <link>https://virgool.io/@javadjahangiri/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%D8%AF%DB%8C%D8%AA%D8%A7%D8%A8%DB%8C%D8%B3-%D8%B1%D8%AF%DB%8C%D8%B3-redis-tutorial-ncdbh74patsq</link>
                <description>به نام آن که جان را فکرت آموخت  /   چراغ دل به نور جان برافروختبا عرض سلام و وقت بخیر خدمت کاربران محترم سایت ویرگول، در این مقاله آموزشی که چکیده آموزش Redis از سایت tutorialspoint بهمراه مطالب تکمیلی تر , سعی شده یک آموزش کاربردی و پروژه محور از دیتابیس Redis ارایه گردد.ایده این سری مقاله های آموزشی از این موضوع سرچشمه می گیرد که بخشی از خوانندگان وجود دارد که به محتوای نوشتاری آنلاین بهتر پاسخ می دهند و ترجیج می دهند مهارت های جدید را به سرعت از طریق خواندن افزایش دهند.این سری اموزش ها با ارایه اولین پکیج آموزشی در خصوص Redis آغاز می شود که انتظار می رود با واکنش مثبت کاربران همراه شود.توجه: این مقاله به مرور زمان، ویرایش و یا تکمیل می‌شود! تقاضا: در صورتی که با مشکل تایپی، دستوری و یا مفهومی در این مقاله برخورد کردید، از شما دوست عزیز و گرامی، صمیمانه تقاضا می‌کنم که اینجانب را مطلع کرده، تا نسبت به تصحیح و یا تکمیل آن، در اسرع وقت، اقدام نمایم. با کمال تشکر جواد جهانگیری  شماره تلفن همراه: 09149431772 نشانی پست الکترونیکی: javad.jahangiri.niopdc@gmail.com فیلم‌های آموزشی در آپارات:جواد جهانگیری (CTO) - آپاراتفیلم آموزشی در یوتویب: javad jahangiri - YouTubeنسخه مقاله: 2.3 - تاریخ بروزرسانی: 1400/11/04 https://www.aparat.com/javadjahangiriniopdc/playlists Redisیک دیتابیس اوپن سورس از نوع NoSQL می باشدمخفف Remote Dictionary Server استبصورت جفت های key-value طراحی شده استیک Data Structure Server محسوب می شودفوق العاده سریع می باشد و داده ها رو RAM نگهداری می کند.امکان ذخیره داده هم روی RAM و هم Disk را دارد.دارای امکانات تجاری از قبیل share ding , Cluster, Sentinel, Replication می باشدبیشتر بعنوان یک Distributed Cache  مورد استفاده قرار می گیرداگر بخواهیم بصورت حرفه ای بررسی کنیم تا این لحظه ن بصورت async کار نمی کند و بصورت (Single instance ) کار می کند و اجرای دستورات بصورت async در افزایش پرفورمانس آن زیاد تاثیر گذار نیستبا توجه به میزان اندازه داده ها به فضای رم نیازمند هستیددر برخی پروژه اگر دیتابیس پروژه کوچک باشد و نیاز به سرعت خیلی بالا باشد می توان بعنوان دیتابیس اصلی پروژه نیز استفاده کرد چون امکاناتی دارد که می تواند داده ها را بصورت پایدار در هارد نیز نگهداری کندکوری های پیشرفته و پیچیده همانند دیتابیس های رابطه ای را پشتیبان نمی کند و در تراکنش ها (transaction) حالت Rollback را پشتیبانی نمی کند و اگر خطای رخ دهد بجای رول بک بقیه دستورات را اجرا می کند.معادل Redis در پروژه های Django می توان به یMemCache اشاره نمودآموزش نحوه نصب Redisدر ابتدای اموزش می خواهیم نحوه نصب Redis را آموزش دهیم با توجه به اینکه دیتابیس Redis بر روی لینوکس می باشد و با مراجعه به سایت Redis مشاهده می کنید که نسخه رسمی برای ویندوز ارایه نشده است برای نصب Redis در ویندوز سه روش وجود دارد که با هم بررسی می کنیماستفاده از Microsoft Archive در گیت هاب استفاده از WSL2 در ویندوز 10استفاده از داکر Docker Desktopروش اول :استفاده از Microsoft Archive در گیت هاببا توجه به اینکه نسخه رسمی از Redis برای ویندوز ارایه نشده است ولی در گیت هاب مایکروسافت ارشیو یک نسخه پورت شده (This is a port for Windows based on Redis) برای توسعه و برنامه نویسی با استفاده از دیتابیس Redis قرار داده شده است این نسخه پورت شده بود و برای مد Product توصیه نمی شود https://github.com/microsoftarchive/redis با مراجعه به سایت گیت از این قسمت نسخه نصبی Redis را دانلود و نصب کنید https://github.com/microsoftarchive/redis/releases و از اخر این صفحه نسخه msi ان را دانلود و نصب می کنیمبعد از نصب Redis بصورت یک سرویس به ویندوز اضافه می شوددر نهایت می توانید وارد Command Prompt ویندوز شده و از طریق دستور Redis-cli وارد کنسول Redis شویم:روش دوم : استفاده از WSL2 در ویندوز 10ابتدا بایستی windows subsystem for Linux و Virtual Machine platform از قسمت windows Features فعال می کنیمسپس از طریق لینک زیر نسبت به نصب WSL2 با دستور زیر اقدام می کنید:wsl --install https://docs.microsoft.com/en-us/windows/wsl/install سپس از طریق Microsoft Store نسبت به نصب Ubuntu در ویندوز اقدام می کنیم:سپس از طریق Microsoft Store نسبت به نصب Windows Terminalدر ویندوز اقدام می کنیم:در نهایت بعد از اتمام مراحل بایستی مطمن شوید که نسخه WSL2 در سیستم شما فعال شده است که برای این کار مطابق تصویر عمل کنید:در نهایت وارد کنسول لینوکس ابونتو در محیط ویندوز می شویم : sudo apt update &amp;&amp;  apt upgradeبعد از اتمام بروزرسانی لینوکس برای نصب Redis دستور زیر را در ترمینال وارد می کنیم :sudo apt install redis-serverودر پاسخ جواب yes راصادر می کنیم تا Redis در لینوکس اوبنتور در wsl2 ویندوز نصب شود و بعد از اتمام نصب می توانیم از دستور زیر سرور Redis را راه اندازی کنیم:redis-serverو در نهایت یک تب جدید در ترمینال ابونتو باز می کنیم و از طریق دستور Redis-Cli وارد کنسول Redis می شویم :نکته :اگر بخواهیم دیتابیس Redis در لینوکس ابونتو بصورت سرویس در پس زمینه اجرا شود از طریق دستور زیر عمل می کنیم:sudo service redis-server startروش سوم نصب و راه اندازی Redis در Dockerروش نصب با داکر برای برنامه نویس توصیه می شود ابتدا وارد سایت docker hub مطابق شکل زیر می شویم و Redis را جستجو می کنیم و از نتایج نسخه official image را پیدا کرده و مطابق مستندات شروع به نصب می کنیممطابق اموزش های قبلی برنامه Docker Desktop را اجرا کرده وارد ترمینال ویندوز شده و ایمیج مربوط را pull می کنیمبعداز پول شده ایمیج می بایستی در لیست ایمیج های داکردسکتاپ ردیس اضافه شده باشدسپس از روی مستندات ایمیج Redis مطابق دستور زیر عمل می کنیمdocker run -d -p 6379:6379 --name aspnetrun-redis redisحالا می توانید از طریق دستور زیر چک کنید که Redis بدرستی اجرا شده استهمچنین می توانید از طریق Docker Desktop نیز اجرا شدن صحیح Redis مطمن شویدنحوه وارد شدن به Redis-cliاز طریق دستور زیر می توایند به محیط اینتر اکتیو مربوط به شل Redis وارد شوید:docker exec -it aspnetrun-redis /bin/bashسپس با وارد کردن Redis-cli وارد خط دستورات Redis می شویم و ادامه اموزش شروع به کار با دستورات Redis می کنیم ،همانطور که می دانید دیتابیس Redis بصورت جفت کلیدهای key/value کار می کند برای تست صحیح بودن عملیات یک کلید بنام name با مقدار javad ایجاد کرده و دوباره اطلاعات ان را به شرح ذیل می خوانیم:برای ذخیره سازی داده ها بصورت عمومی  در ردیس ما پنج گزینه در اختیار داریم:stringListSethashSorted Setهمانگونه که اشاره کردیم Redis یک دیتابیس In Memory می باشد و داده ها را در Ram نگهداری می کند و دارای سرعت خیلی زیادی می باشد ولی یکی از امکاناتی در ردیس داریم امکانات نگهداری داده ها بصورت دایمی می باشدبرای نگهداری داده های ردیس در هارد بصورت دایمی بصورت کلی دو روش داریم روش اول که Point-in-time dump می باشد که در این روش ردیس اطلاعات در بازه های زمانی برای مثال هر ده ثانیه یکبار و یا براساس میزان تغییرات دیتابیس تنظیم می شود برای مثال هر صد تغییر در دیتابیس بر روی هارد ذخیره شود روش دوم که به آن Append-only گفته می شوداز لحظه ای که سرویس ردیس راه اندازی می شود هر تغییری در یک فایل بر روی هارد بصورت فقط افزایشی نوشته می شود در این حالت ردیس یک مقدار کند می شود زیرا باید هر تغییرات از RAM بر روی هارد دیسک نوشته شود که باعث افت پرفورمانس ردیس می شود از سوی دیگر مشکل دیگر این است که اندازه این فایل بصورت خیلی سریع افزایش پیدامی کند که شاید بر روی سرور شما فضای کافی برای نگهداری داده ها موجود نباشد زیرا هر تغییری حتی اگر حذف هم شود در این فایل بصورت یک history نگهداری می شود لذا باعث افزایش تدریجی اندازه این فایل می شود این روش بیشتر بصورت یک log از تغییرات استفاده می شود.در ادامه اموزش شروع به بررسی دیتابیس Redis  می کنیم مطابق اموزش های قبلی بعنوان منبع اموزشی از سایت https://www.tutorialspoint.com استفاده می کنیم: https://www.tutorialspoint.com/redis/index.htm Redis - HomeRedis Tutorialردیس یه برنامه اوپن سورس با مجوز BSD و در حقیقت یک دخیره ساز پیشرفته key/value می باشد اغلب از آن به عنوان سرور ساختار داده یاد می شود، زیرا کلیدها می توانند شامل رشته ها، هش ها، لیست ها، مجموعه ها و مجموعه های مرتب شده باشند. Redis به زبان C نوشته شده است. این آموزش درک خوبی از مفاهیم Redis، مورد نیاز برای ایجاد و استقرار یک سیستم بسیار مقیاس پذیر و عملکرد محور را ارائه می دهد.Audienceاین آموزش برای برای برنامه نویسان و معماران نرم افزار که مایل به یادگیری Redis در مراحل ساده و آسان هستند طراحی شده است. پس از تکمیل این آموزش، شما در سطح متوسطی از تخصص خواهید بود که از آنجا می توانید خود را به سطح بالاتری از تخصص ببرید.Prerequisitesقبل از ادامه این آموزش، باید دانش اولیه در مورد ساختارهای داده داشته باشیدRedis - Overviewردیس (Redis)  یک برنامه اوپن سورس ، یک منبع ذخیزه پیشرفته بصورت key/value  می باشد  و یک راه حل مناسب برای ساخت برنامه های کاربردی وب با کارایی بالا و مقیاس پذیر است. Redis دارای سه ویژگی اصلی است که آن را متمایز می کند. ردیس پایگاه داده خود را به طور کامل در حافظه نگه می دارد و از دیسک فقط برای ماندگاری استفاده می کند. ردیس در مقایسه با بسیاری از ذخیره‌سازی‌های داده با ارزش کلید، مجموعه نسبتاً غنی از انواع داده‌ها دارد. ردیس می تواند داده ها را به هر تعداد Slave کپی کند.Redis Advantagesدر زیر مزایای خاصی از Redis بررسی می شود:Exceptionally fast ردیس بسیار سریع است و می تواند حدود 110000 SET در ثانیه، حدود 81000 GET در ثانیه انجام دهد.Supports rich data typesردیس بطور بومی از بسیاری از انواع داده هایی که توسعه دهندگان از قبل می شناسند مانند لیست، مجموعه، مجموعه مرتب شده و هش پشتیبانی می کند. این امر حل انواع مشکلات را آسان می کند زیرا می دانیم کدام مشکل با کدام نوع داده بهتر قابل رسیدگی استOperations are atomicتمام عملیات Redis اتمیک هستند، که تضمین می کند که اگر دو مشتری به طور همروند درخواست دسترسی به داده ای را داشته باشند، سرور Redis مقدار به روز شده (آخرین به روزرسانی )را ارایه می کندMulti-utility toolردیس یک ابزار چندکاربردی است و می‌تواند در موارد متعددی مانند ذخیره‌سازی، صف‌های پیام‌رسانی مورد استفاده قرار گیرد (Redis به طور بومی از Publish پشتیبانی می‌کند).Redis Versus Other Key-value Storesردیس یک مسیر تکاملی متفاوت در مقایسه با database های از نوع key/values را طی می کند، که در آن مقادیر می‌توانند حاوی انواع داده‌های پیچیده‌تر باشند و عملیات اتمیک روی آن نوع داده‌ها تعریف شده است.ردیس یک پایگاه داده بر روی حافظه است اما می تواند اطلاعات برای ماندگاری رو هارد دیسک هم بنویسد، از این رو نشان دهنده یک معامله متفاوت است که در آن سرعت نوشتن و خواندن بسیار بالا با محدودیت مجموعه داده هایی که نمی توانند بزرگتر از حافظه باشند به دست می آید.مزیت دیگر پایگاه های داده درون حافظه این است که نمایش حافظه ساختارهای داده پیچیده در مقایسه با ساختار داده مشابه روی دیسک بسیار ساده تر است. بنابراین، Redis می تواند کارهای زیادی را با پیچیدگی داخلی کمی انجام دهد.Redis - Configurationدر Redis، یک فایل پیکربندی (redis.conf) در دایرکتوری ریشه Redis موجود است. اگرچه می توانید تمام تنظیمات Redis را با دستور Redis CONFIG دریافت و تنظیم کنید.SyntaxFollowing is the basic syntax of Redis CONFIG command.redis 127.0.0.1:6379&gt; CONFIG GET CONFIG_SETTING_NAMEExampleredis 127.0.0.1:6379&gt; CONFIG GET loglevel  
1) &amp;quotloglevel&amp;quot 
2) &amp;quotnotice&amp;quotTo get all configuration settings, use * in place of CONFIG_SETTING_NAMEExampleredis 127.0.0.1:6379&gt; CONFIG GET *Edit Configurationبرای به‌روزرسانی پیکربندی، می‌توانید فایل redis.conf را مستقیماً ویرایش کنید یا می‌توانید تنظیمات را از طریق دستور CONFIG set به‌روزرسانی کنید.SyntaxFollowing is the basic syntax of CONFIG SET command.redis 127.0.0.1:6379&gt; CONFIG SET CONFIG_SETTING_NAME NEW_CONFIG_VALUEExampleredis 127.0.0.1:6379&gt; CONFIG SET loglevel &amp;quotnotice&amp;quot 
OK 
redis 127.0.0.1:6379&gt; CONFIG GET loglevel  
1) &amp;quotloglevel&amp;quot 
2) &amp;quotnotice&amp;quotتوجه شود ردیس دارای چهار حالت لاگ گیری می باشدRedis has four log levels: debug, verbose, notice, and warning.که در این مثال loglevel  بر روی notice تنظیم شده است دقت کنید حالت پیش فرض لاگ گیری هم notice می باشد.Redis - Data Typesردیس از 5 نوع نوع داده پشتیبانی می کند.Stringsرشته Redis دنباله ای از بایت است. رشته‌ها در Redis دودویی امن هستند، به این معنی که طول مشخصی دارند و انتهای متن توسط هیچ کاراکتر پایان‌دهنده خاصی تعیین نمی‌شود. بنابراین، شما می توانید هر چیزی تا 512 مگابایت را در یک رشته ذخیره کنید.Exampleredis 127.0.0.1:6379&gt; SET name &amp;quottutorialspoint&amp;quot 
OK 
redis 127.0.0.1:6379&gt; GET name 
&amp;quottutorialspoint&amp;quot
در مثال بالا، SET و GET دستورات Redis هستند، name کلید استفاده شده در Redis و tutorialspoint مقدار رشته ای است که در Redis ذخیره می شود.نکته:حداکثر سایز یک رشته در در ردیس 512 مگابایت می باشد و اگر کلیدی حذف شده و یا ایجاد نشده باشد و درخواست شود Redis مقدار (nil) به معنی NULL را برگشت می دهدListsلیست های Redis به سادگی لیستی از رشته ها هستند که بر اساس ترتیب درج مرتب شده اند. می توانید عناصر را در لیست های Redis در head یا tail لیست اضافه کنید. حداکثر طول یک لیست  بیش از 4 میلیارد عنصر در هر لیست می باشد.در حقیقت یک Linked list هستند که برای مطالعه بیشتر به سایت wiki مراجعه نمایید فقط توجه شود در ردیس لیست ها بصورت تک طرفه Singly linked list پیداسازی می شود ولی اگر حضور ذهن داشته باشید در اموزش ها سی شارپ توضیح داده ام که در سی شارپ لیست ها بصورت Doubly linked list می باشد دو جهت بوده و می توان در دو جهت از اول به اخر یا از اخر به اول پیمایش شود.Exampleredis 127.0.0.1:6379&gt; LPUSH tutorials redis 
(integer) 1 
redis 127.0.0.1:6379&gt; LPUSH tutorials mongodb 
(integer) 2 
redis 127.0.0.1:6379&gt; LPUSH tutorials mysql 
(integer) 3 
redis 127.0.0.1:6379&gt; LRANGE tutorials 0 10  
1) &amp;quotmysql&amp;quot 
2) &amp;quotmongodb&amp;quot 
3) &amp;quotredis&amp;quotExample:Hashesهش Redis مجموعه‌ای از جفت‌های ارزش کلیدی است. هش های Redis نقشه هایی بین فیلدهای رشته و مقادیر رشته هستند. از این رو، از آنها برای نمایش اشیا استفاده می شود.برای مطالعه بیشتر در مورد hash پیشنهاد می دهم ابتدا اموزش های بنده را در این راستا در آپارات را مطالعه نمایید https://www.aparat.com/v/UVJ7O  https://www.aparat.com/v/Ya5dg Exampleredis 127.0.0.1:6379&gt; HMSET user:1 username tutorialspoint password 
tutorialspoint points 200 
OK 
redis 127.0.0.1:6379&gt; HGETALL user:1  
1) &amp;quotusername&amp;quot 
2) &amp;quottutorialspoint&amp;quot 
3) &amp;quotpassword&amp;quot 
4) &amp;quottutorialspoint&amp;quot 
5) &amp;quotpoints&amp;quot 
6) &amp;quot200&amp;quotدر مثال بالا، از نوع داده هش برای ذخیره شی کاربر استفاده می شود که حاوی اطلاعات اولیه کاربر است.در اینجا HMSET، HGETALL دستوراتی برای Redis هستند، در حالی که کلید جستجو user-1  می باشدEvery hash can store up to (more than 4 billion field-value pairs).لیست های Redis به سادگی لیستی از رشته ها هستند که بر اساس ترتیب درج مرتب شده اند. شما می توانید عناصر را به لیست Redis در head یا tail اضافه کنید.Exampleredis 127.0.0.1:6379&gt; lpush tutoriallist redis 
(integer) 1 
redis 127.0.0.1:6379&gt; lpush tutoriallist mongodb 
(integer) 2 
redis 127.0.0.1:6379&gt; lpush tutoriallist rabitmq 
(integer) 3 
redis 127.0.0.1:6379&gt; lrange tutoriallist 0 10  

1) &amp;quotrabitmq&amp;quot 
2) &amp;quotmongodb&amp;quot 
3) &amp;quotredis&amp;quotThe max length of a list is 4294967295, more than 4 billion of elements per listSetsمجموعه‌های Redis مجموعه‌ای نامرتب از رشته‌ها هستند. در Redis، می توانید اضافه کنید، حذف کنید، و وجود اعضا را در پیچیدگی زمانی O(1) آزمایش کنید.Exampleredis 127.0.0.1:6379&gt; sadd tutoriallist redis 
(integer) 1 
redis 127.0.0.1:6379&gt; sadd tutoriallist mongodb 
(integer) 1 
redis 127.0.0.1:6379&gt; sadd tutoriallist rabitmq 
(integer) 1 
redis 127.0.0.1:6379&gt; sadd tutoriallist rabitmq 
(integer) 0 
redis 127.0.0.1:6379&gt; 

1) &amp;quotrabitmq&amp;quot 
2) &amp;quotmongodb&amp;quot 
3) &amp;quotredنکته:در مثال بالا، rabbitmq دو بار اضافه شده است، اما به دلیل ویژگی منحصر به فرد مجموعه(set عضو تکراری را ثبت نمی کند)، تنها یک بار اضافه می شود.The max number of members in a set is 4294967295, more than 4 billion of members per set.Sorted Setsمجموعه‌های مرتب‌شده Redis مشابه مجموعه‌های Redis هستند، مجموعه‌های غیر تکراری رشته‌ها. تفاوت این است که هر عضو یک مجموعه مرتب شده با یک امتیاز همراه است که برای گرفتن مجموعه مرتب شده از کوچکترین به بزرگترین امتیاز استفاده می شود. در حالی که اعضا منحصر به فرد هستند، امتیازها ممکن است تکرار شوند.redis 127.0.0.1:6379&gt; zadd tutoriallist 0 redis 
(integer) 1 
redis 127.0.0.1:6379&gt; zadd tutoriallist 0 mongodb 
(integer) 1 
redis 127.0.0.1:6379&gt; zadd tutoriallist 0 rabitmq 
(integer) 1 
redis 127.0.0.1:6379&gt; zadd tutoriallist 0 rabitmq 
(integer) 0 
redis 127.0.0.1:6379&gt; ZRANGEBYSCORE tutoriallist 0 1000  

1) &amp;quotredis&amp;quot 
2) &amp;quotmongodb&amp;quot 
3) &amp;quotrabitmq&amp;quotHow To Manage Redis Databasesردیس دارای 16 دیتابیس می باشد که از شماره 0 تا 15 شماره گذاری شده است و بصورت پیش فرض در هنگام اتصال به ردیس اطلاعات در دیتابیس شماره 0 ذخیره می شوداز طریق دستور select  می توانیم دیتابیس مورد نظر را انتخاب کنیم To swap all the data held in one database with the data held in anotherاز طریق دستور swapdb می توان تمامی داده های موجود در یک دیتابیس را ردیس را به دیتابیس دیگر ردیس منتقل کردد swapdb 15 14Redis CommandsRedis - Commandsدستورات Redis برای انجام برخی عملیات روی سرور Redis استفاده می شود. برای اجرای دستورات روی سرور Redis، به یک کلاینت Redis نیاز دارید. کلاینت Redis در پکیج ردیس موجود است که قبلاً آن را نصب کرده ایم.SyntaxFollowing is the basic syntax of Redis client.$redis-cliExampleمثال زیر توضیح می دهد که چگونه می توانیم مشتری Redis را راه اندازی کنیم. برای راه اندازی مشتری Redis، ترمینال را باز کرده و دستور redis-cli را تایپ کنید. این به سرور محلی شما متصل می شود و اکنون می توانید هر دستوری را اجرا کنید.$redis-cli 
redis 127.0.0.1:6379&gt; 
redis 127.0.0.1:6379&gt; PING  
PONGدر مثال بالا، ما به سرور Redis در حال اجرا در ماشین محلی متصل می شویم و یک دستور PING را اجرا می کنیم که بررسی می کند آیا سرور در حال اجرا است یا خیر.Run Commands on the Remote Serverبرای اجرای دستورات روی سرور راه دور Redis، باید توسط همان کلاینت redis-cli به سرور متصل شوید.Syntax$ redis-cli -h host -p port -a passwordExampleمثال زیر نحوه اتصال به سرور از راه دور Redis را نشان می دهد که روی هاست 127.0.0.1 اجرا می شود، پورت 6379 و دارای رمز عبور mypass است.$redis-cli -h 127.0.0.1 -p 6379 -a &amp;quotmypass&amp;quot 
redis 127.0.0.1:6379&gt; 
redis 127.0.0.1:6379&gt; PING  
PONGRedis - Keysدستورات Redis keys برای مدیریت کلیدها در Redis استفاده می شود. در زیر نحوه استفاده از دستورات کلیدهای redis آمده است.Syntaxredis 127.0.0.1:6379&gt; COMMAND KEY_NAMEExampleredis 127.0.0.1:6379&gt; SET tutorialspoint redis 
OK 
redis 127.0.0.1:6379&gt; DEL tutorialspoint 
(integer) 1در مثال بالا، DEL فرمان است، در حالی که tutorialspoint کلید است. اگر کلید حذف شود، خروجی دستور (عدد صحیح) 1 و در غیر این صورت (عدد صحیح) 0 خواهد بود.Rename Keysبرای تغییر نام یک کلید از دستور زیر استفاده می  کنیم rename   old_key   new_keyRedis Keys CommandsFollowing table lists some basic commands related to keys.در ردیس expire برای مشخص کردن زمان از بین رفتن یک کلید براساس ثانیه می باشد و ttl نیز زمان باقیمانده برای از بین رفتن کلید را نمایش می دهد اگر عدد -2 را نمایش دهد به معنی key does not exis می باشد یعنی کلید حذف شده است و اگر عدد -1 نمایش دهد  key exists but has no associated expire به معنی کلید وجود دارد و زمان ان منقضی نشده است(حالت نرمال در ttl عدد -1 را نمایش می دهد )redis&gt; SET mykey &amp;quotHello&amp;quot
&amp;quotOK&amp;quot
redis&gt; EXPIRE mykey 10
(integer) 1
redis&gt; TTL mykey
(integer) 10
redis&gt; Redis - Stringsدستورات رشته های Redis برای مدیریت مقادیر رشته در Redis استفاده می شود. در زیر نحوه استفاده از دستورات رشته Redis آمده است.Syntaxredis 127.0.0.1:6379&gt; COMMAND KEY_NAMEExampleredis 127.0.0.1:6379&gt; SET tutorialspoint redis 
OK 
redis 127.0.0.1:6379&gt; GET tutorialspoint 
&amp;quotredis&amp;quotIn the above example, SET and GET are the commands, while tutorialspoint is the key.Redis Strings CommandsFollowing table lists some basic commands to manage strings in Redis.Redis - Hashesهش های ردیس برای مپ کردن بین فیلدهای رشته و مقادیر رشته هستند. از این رو، آنها بهترین نوع داده برای نمایش اشیا هستند. در ردیس، هر هش می تواند بیش از 4 میلیارد جفت فیلد-مقدار را ذخیره کندExampleredis 127.0.0.1:6379&gt; HMSET tutorialspoint name &amp;quotredis tutorial&amp;quot 
description &amp;quotredis basic commands for caching&amp;quot likes 20 visitors 23000 
OK 
redis 127.0.0.1:6379&gt; HGETALL tutorialspoint  
1) &amp;quotname&amp;quot 
2) &amp;quotredis tutorial&amp;quot 
3) &amp;quotdescription&amp;quot 
4) &amp;quotredis basic commands for caching&amp;quot 
5) &amp;quotlikes&amp;quot 
6) &amp;quot20&amp;quot 
7) &amp;quotvisitors&amp;quot 
8) &amp;quot23000&amp;quotدر مثال بالا، جزئیات آموزش های Redis (نام، توضیحات، لایک ها، بازدیدکنندگان) را به صورت هش با نام &quot;tutorialspoint&quot; تنظیم کرده ایم.Redis Hash CommandsFollowing table lists some basic commands related to hash.Redis - Listsلیست های Redis به سادگی لیستی از رشته ها هستند که بر اساس ترتیب درج مرتب شده اند. می توانید عناصر را در لیست های Redis در head یا tail لیست اضافه کنید. حداکثر طول یک لیست 2^32 - 1 عنصر است (4294967295، بیش از 4 میلیارد عنصر در هر لیست).Exampleredis 127.0.0.1:6379&gt; LPUSH tutorials redis 
(integer) 1 
redis 127.0.0.1:6379&gt; LPUSH tutorials mongodb 
(integer) 2 
redis 127.0.0.1:6379&gt; LPUSH tutorials mysql 
(integer) 3 
redis 127.0.0.1:6379&gt; LRANGE tutorials 0 10  
1) &amp;quotmysql&amp;quot 
2) &amp;quotmongodb&amp;quot 
3) &amp;quotredis&amp;quotدر مثال بالا، سه مقدار با دستور LPUSH در لیست Redis به نام &quot;آموزش&quot; درج شده است.Redis Lists CommandsFollowing table lists some basic commands related to lists.Redis - Setsمجموعه‌های Redis مجموعه‌ای نامرتب از رشته‌های منحصربه‌فرد هستند. منحصر به فرد به این معنی است که مجموعه ها اجازه تکرار داده ها را در یک کلید نمی دهند. در مجموعه Redis وجود اعضا را در O(1) اضافه، حذف و آزمایش کنید (زمان ثابت بدون توجه به تعداد عناصر موجود در مجموعه). حداکثر طول یک لیست 2^32 - 1 عنصر است (4294967295، بیش از 4 میلیارد عنصر در هر مجموعه).Exampleredis 127.0.0.1:6379&gt; SADD tutorials redis 
(integer) 1 
redis 127.0.0.1:6379&gt; SADD tutorials mongodb 
(integer) 1 
redis 127.0.0.1:6379&gt; SADD tutorials mysql 
(integer) 1 
redis 127.0.0.1:6379&gt; SADD tutorials mysql 
(integer) 0 
redis 127.0.0.1:6379&gt; SMEMBERS tutorials  
1) &amp;quotmysql&amp;quot 
2) &amp;quotmongodb&amp;quot 
3) &amp;quotredis&amp;quotدر مثال بالا، با دستور SADD، سه مقدار در مجموعه Redis با نام &quot;tutorials&quot; درج شده است.Redis Sets CommandsFollowing table lists some basic commands related to sets.Redis - Sorted Setsمجموعه‌های مرتب‌شده Redis مشابه مجموعه‌های Redis با ویژگی منحصربه‌فرد مقادیر ذخیره‌شده در یک مجموعه هستند. تفاوت این است که هر عضو یک مجموعه مرتب شده با یک امتیاز همراه است که برای گرفتن مجموعه مرتب شده از کوچکترین به بزرگترین امتیاز استفاده می شود. در مجموعه مرتب‌سازی شده Redis، وجود اعضا را در O(1) اضافه، حذف و آزمایش کنید (زمان ثابت بدون توجه به تعداد عناصر موجود در مجموعه). حداکثر طول یک لیست 2^32 - 1 عنصر است (4294967295، بیش از 4 میلیارد عنصر در هر مجموعه).Exampleredis 127.0.0.1:6379&gt; ZADD tutorials 1 redis 
(integer) 1 
redis 127.0.0.1:6379&gt; ZADD tutorials 2 mongodb 
(integer) 1 
redis 127.0.0.1:6379&gt; ZADD tutorials 3 mysql 
(integer) 1 
redis 127.0.0.1:6379&gt; ZADD tutorials 3 mysql 
(integer) 0 
redis 127.0.0.1:6379&gt; ZADD tutorials 4 mysql 
(integer) 0 
redis 127.0.0.1:6379&gt; ZRANGE tutorials 0 10 WITHSCORES  
1) &amp;quotredis&amp;quot 
2) &amp;quot1&amp;quot 
3) &amp;quotmongodb&amp;quot 
4) &amp;quot2&amp;quot 
5) &amp;quotmysql&amp;quot 
6) &amp;quot4&amp;quot
در مثال بالا، سه مقدار به همراه امتیاز آن در مجموعه مرتب‌سازی شده Redis به نام «آموزش» با دستور ZADD درج شده است.Redis Sorted Sets CommandsFollowing table lists some basic commands related to sorted sets.Redis - HyperLogLogردیس HyperLogLog الگوریتمی است که از تصادفی سازی استفاده می کند تا تقریبی از تعداد عناصر منحصر به فرد در یک مجموعه را با استفاده از مقدار ثابت و کمی حافظه ارائه دهد. این الگوریتم HyperLogLog تقریب بسیار خوبی از کاردینالیته یک مجموعه حتی با استفاده از مقدار بسیار کمی از حافظه در حدود 12 کیلوبایت در هر کلید با خطای استاندارد 0.81٪ ارائه می دهد. هیچ محدودیتی برای تعداد مواردی که می توانید بشمارید وجود ندارد، مگر اینکه به ^642 مورد نزدیک شوید.بصورت خلاصه می توان گفت این ساختار با حذف عناصر تکراری ، با سریعترین روش و کمترین میزان حافظه می تواند تعداد عناصر موجود در این ساختار را شمارش کندExampleFollowing example explains how Redis HyperLogLog works.redis 127.0.0.1:6379&gt; PFADD tutorials &amp;quotredis&amp;quot  
1) (integer) 1  
redis 127.0.0.1:6379&gt; PFADD tutorials &amp;quotmongodb&amp;quot  
1) (integer) 1  
redis 127.0.0.1:6379&gt; PFADD tutorials &amp;quotmysql&amp;quot  
1) (integer) 1  
redis 127.0.0.1:6379&gt; PFCOUNT tutorials  
(integer) 3
Redis HyperLogLog CommandsFollowing table lists some basic commands related to Redis HyperLogLog.Redis - HyperLogLog Pfadd Commandدستور Redis PFADD تمام آرگومان های عنصر را به ساختار داده HyperLogLog که در نام کلید مشخص شده به عنوان اولین آرگومان ذخیره شده است اضافه می کند.Return ValueInteger reply, 1 or 0.SyntaxFollowing is the basic syntax of Redis PFADD command.redis 127.0.0.1:6379&gt; PFADD KEY_NAME ELEMENTS_TO_BE_ADDEDExampleredis 127.0.0.1:6379&gt; PFADD mykey a b c d e f g h i j 
(integer) 1 
redis 127.0.0.1:6379&gt; PFCOUNT mykey 
(integer) 10Redis - HyperLogLog Pfcount Commandدستور Redis PFCOUNT برای به دست آوردن کاردینالیتی تقریبی محاسبه شده توسط ساختار داده HyperLogLog ذخیره شده در متغیر مشخص شده استفاده می شود. اگر کلید وجود نداشته باشد، 0 را برمی گرداند.Return ValueInteger reply, approximated number of unique elements.When PFCOUNT command is used with multiple keys, then it returns approximated cardinality of the union of the HyperLogLogs.SyntaxFollowing is the basic syntax of Redis PFCOUNT command.redis 127.0.0.1:6379&gt; PFCOUNT KEY1 KEY@... KEYNExampleredis 127.0.0.1:6379&gt; PFADD mykey a b c d e f g h i j 
(integer) 1 
redis 127.0.0.1:6379&gt; PFCOUNT mykey 
(integer) 10 
redis 127.0.0.1:6379&gt; PFCOUNT mykey 
(integer) 10 
redis 127.0.0.1:6379&gt; PFCOUNT mykey mynewkey 
(integer) 10Redis - HyperLogLog Pfmerge Commandدستور Redis PFMERGE برای ادغام چندین مقدار HyperLogLog در یک مقدار منحصر به فرد استفاده می‌شود که تقریباً اصلی بودن اتحاد مجموعه‌های مشاهده‌شده ساختارهای HyperLogLog مبدا را نشان می‌دهد.Return ValueSimple string reply OK.SyntaxFollowing is the basic syntax of Redis PFMERGE command.redis 127.0.0.1:6379&gt; PFMERGE KEY1 KEY@... KEYNExampleredis 127.0.0.1:6379&gt; PFADD hll1 foo bar zap a 
(integer) 1 
redis 127.0.0.1:6379&gt; PFADD hll2 a b c foo 
(integer) 1 
redis 127.0.0.1:6379&gt; PFMERGE hll3 hll1 hll2 
OK 
redis 127.0.0.1:6379&gt; PFCOUNT hll3 
(integer) 6Redis - Publish SubscribeدرRedis Pub/Sub سیستم پیام رسانی را پیاده سازی می کند که در آن فرستنده در اصطلاح redis به نام ناشر(publishers) پیام ها را ارسال می کند در حالی که گیرندگان مشترکین(subscribers) آنها را دریافت می کنند. لینکی که پیام ها توسط آن منتقل می شوند کانال (channel) نامیده می شود.در Redis، مشتری می تواند هر تعداد کانال را مشترک کند.Exampleمثال زیر نحوه عملکرد مفهوم مشترک را توضیح می دهد. در مثال زیر، یکی از مشتریان کانالی به نام «redisChat» را مشترک می‌کندredis 127.0.0.1:6379&gt; SUBSCRIBE redisChat  
Reading messages... (press Ctrl-C to quit) 
1) &amp;quotsubscribe&amp;quot 
2) &amp;quotredisChat&amp;quot 
3) (integer) 1
اکنون، دو مشتری پیام‌ها را در یک کانال به نام «redisChat» منتشر می‌کنند و مشتری مشترک بالا در حال دریافت پیام است.redis 127.0.0.1:6379&gt; PUBLISH redisChat &quot;Redis is a great caching technique&quot;  (integer) 1  redis 127.0.0.1:6379&gt; PUBLISH redisChat &quot;Learn redis by tutorials point&quot;  (integer) 1   1) &quot;message&quot; 2) &quot;redisChat&quot; 3) &quot;Redis is a great caching technique&quot; 1) &quot;message&quot; 2) &quot;redisChat&quot; 3) &quot;Learn redis by tutorials point&quot;Redis PubSub CommandsFollowing table lists some basic commands related to Redis Pub/Sub.Redis - Transactionsتراکنش های Redis امکان اجرای گروهی از دستورات را در یک مرحله واحد فراهم می کند. در زیر دو ویژگی تراکنش ها آورده شده است.تمام دستورات در یک تراکنش به صورت متوالی به عنوان یک عملیات مجزا اجرا می شوند. این امکان وجود ندارد که درخواستی که توسط مشتری دیگری صادر شده است در میانه اجرای تراکنش Redis اجرا شود.تراکنش Redis نیز اتمی است. اتمی به این معنی است که یا همه دستورات پردازش نمی شوند یا هیچ کدامSampleتراکنش Redis با دستور MULTI آغاز می شود و سپس باید لیستی از دستوراتی را که باید در تراکنش اجرا شوند ارسال کنید و پس از آن کل تراکنش با دستور EXEC اجرا می شود.redis 127.0.0.1:6379&gt; MULTI 
OK 
List of commands here 
redis 127.0.0.1:6379&gt; EXEC
ExampleFollowing example explains how Redis transaction can be initiated and executed.redis 127.0.0.1:6379&gt; MULTI 
OK 
redis 127.0.0.1:6379&gt; SET tutorial redis 
QUEUED 
redis 127.0.0.1:6379&gt; GET tutorial 
QUEUED 
redis 127.0.0.1:6379&gt; INCR visitors 
QUEUED 
redis 127.0.0.1:6379&gt; EXEC  
1) OK 
2) &amp;quotredis&amp;quot 
3) (integer) 1Redis Transaction CommandsFollowing table shows some basic commands related to Redis transactions.در دیتابیس‌های رابطه ای جهت اجرای چندین دستور اعم از ایجاد، به‌روزرسانی و حذف، از تراکنش یا Transaction ها استفاده می‌شود. هر تراکنش باید قوانین ACID را رعایت کند، در غیر اینصورت قابل‌اجرا نمی‌باشد. این قوانین با استفاده از نوعی سیستم قفل گذاری پیاده سازی شده‌اند.قوانین ACID شامل موارد ذیل است که باید در تراکنش دیتابیس‌های رابطه ای رعایت گردد:• Atomicity: این خاصیت که به خاصیت همه یا هیچ معروف است، بیانگر این است که یک تراکنش یا باید به طور کامل اجرا شود یا اصلا اجرا نشود. برای مثال اگر در یک تراکنش سه عملیات مختلف انجام گیرد، یا هر سه این عملیات باید تا پایان تراکنش به صورت کامل انجام شوند یا هیچ کدام از آن‌ها انجام نشوند. دستورات باید به ترتیب و سریالی انجام گیرند و در صورتی که مشکلی در سیستم به وجود آمد (مثلا برق قطع شد)، سیستم باید بعد از اتصال دوباره، عملیات ها را Rollback نماید، به این ترتیب که گویا هیچ کدام از دستورات صورت نگرفته است.• Consistency: برای درک درست مفهوم سازگاری، مثال تراکنش های بانک را در نظر بگیرید. در یک سیستم حسابداری بانک، مجموعه پول های انتقالی بین بانک باید ثابت باشد. در نظر بگیرید که مثلا اگر ۵۰ هزار تومان از حساب کاربری A به حساب کاربری B منتقل شد، مجموعه پول های موجود در بانک تغییر نخواهد کرد. این همان مفهوم سازگاری است. یعنی یک تراکنش، دیتابیس را از یک حالت سازگار به یک حالت سازگار دیگر انتقال می‌دهد.• Isolation: فرض کنید در یک دیتابیس، چندین تراکنش با یکدیگر در حال اجرا هستند. هر تراکنش نباید از اجرای دیگر تراکنش ها مطلع شود. یعنی این تراکنش ها باید طوری اجرا شوند که انگار، فقط همین یک تراکنش در حال اجرا در کل دیتابیس است.• Durability : به این معناست که یک تراکنش بعد از اتمام، باید در حافظه باقی بماند. یعنی اگر یک تراکنش با موفقیت به اتمام رسید، نتایج کار، با قطع برق یا اتفاق های دیگر از بین نرود.تراکنش در Redisردیس از قوانین ACID فقط دو قانون یعنی Isolationو Atomicityرا رعایت می‌کند و قوانین دیگر را بر عهده برنامه‌نویس می‌گذارد.Redis با استفاده از دستورات زیر که در دو بخش است ، تراکنش ها را مدیریت و اجرا می‌کند.1. MULTI, EXEC, DISCARD – دستوراتی جهت ورود به تراکنش و خروج از آن.2. WATCH, UNWATCH – مشاهده یک کلید خاص جهت تغییرات آن توسط client های دیگر.نحوه استفاده از تراکنش در Redisتراکنش با دستور MULTI شروع می‌شود، این دستور همیشه پاسخ &quot;OK&quot; را برگشت می‌دهد. سپس دستورات وارد شده بعد از آن صف بندی می‌شوند و با دستور EXEC دستورات موجود در صف به ترتیب اجرا می‌شوند و تراکنش پایان می‌یابددر صورت استفاده از DISCARD به جای EXEC کل دستورات موجود در صف حذف شده و تراکنش پایان می‌یابد.همان‌طور که در شکل زیر قابل‌مشاهده است پاسخ EXEC یک آرایه است و هر کدام از مقادیر آرایه نتیجه اجرای هر کدام از دستورات است و چون دستورات به صورت ترتیبی انجام می‌گیرد ترتیب مقادیر آرایه نیز با ترتیب اجرای دستورات هماهنگ است.نمونه‌ای از کد تراکنش در ردیس را مشاهده کنید :$ret = $redtis-&gt;multi( )
	-&gt;set(&#039;key1&#039;, ‘val1&#039;)
	-&gt;get(&#039;keyl1&#039; )
	-&gt;set(&#039;key2&#039;, ‘val2&#039;)
	-&gt;get(&#039;key2&#039; )
	-&gt;exec&#40; &#41;;
/*
      $ret == Array(
0 =&gt; TRUE,
1 =&gt; &#039;val1&#039;, 
2 =&gt; TRUE,
 3 =&gt; ‘val2&#039;
     );
*/در صورتی که یک client با سرور ردیس ارتباط داشته باشد استفاده از دستورات بالا صحیح می‌باشد ولی اگر چند client با سرور در ارتباط باشند احتمال خرابی داده موجود در سرور وجود دارد. جهت جلوگیری از خرابی داده می‌باید از WATCH , UNWATCH استفاده کرد.دستور WATCH جهت مشاهده تغییرات کلید خاص توسط client های دیگر استفاده می‌شود و دستور UNWATCH برای پاک کردن مشاهدات client موجود استفاده می‌گردد.$redis-&gt;watch( &#039;x&#039;);
$ret = $redis-&gt;multi( )
	-&gt;incr(&#039;x&#039;)
	-&gt;exec&#40;&#41;;
/*
        $ret = FALSE if x has been modifted between
        the call to WATCH and the call to EXEC.
*/در شکل بالا اگر کلید &quot;x&quot; توسط client دیگری watch شده بود و در حال استفاده بود، نتیجه False برمی گرداند و تراکنش مورد نظر می­ بایست در زمان دیگری اجرا گردد تا اگر client مورد نظر کلید &quot;x&quot; را رها (UNWATCH) کرده بود تراکنش اجرا گردد.خطاها و مدیریت آن­هادر طول یک تراکنش امکان رخداد دو نوع خطا وجود دارد که در ادامه به آن‌ها خواهیم پرداخت.• ممکن است یک دستور در صف قرار نگیرد ، بنابراین ممکن است قبل از فراخوانی دستور EXEC خطایی رخ دهد. به عنوان مثال دستور وارد شده اشتباه باشد (تعداد آرگومان اشتباه ، نام فرمان اشتباه و ...) یا ممکن است شرایط بحرانی مانند پر شدن حافظه وجود داشته باشد (اگر تنظیم سرور برای maxmemory تنظیم شده باشد). که در این صورت داده مورد نظر خراب نشده و تا اینجا Consistency رعایت می‌شود.• یک خطا ممکن است پس از فراخوانی EXEC اتفاق بیافتد. به عنوان مثال از آنجا که ما عملیاتی را بر روی یک کلید با مقدار اشتباه انجام دادیم (مانند فراخوانی یک عملیات لیست در برابر یک مقدار رشته). در شکل زیر این خطا را ملاحظه می فرمایید.&gt; MULTI
    OK
 &gt; set x &amp;quotabc&amp;quot
    QUEUED
 &gt; lpop a
    QUEUED
 &gt; EXEC
   +0K

 -ERR Operation against a key holding the wrong kind of valueدستور EXEC پاسخ دو رشته عناصر را بر می گرداند که یکی &quot;OK&quot; و پاسخ دیگری ERR است که وظیفه ی برنامه‌نویس یافتن راه حلی منطقی برای کنترل خطا و انتقال آن به کاربر است.توجه به این نکته مهم است که حتی هنگامی که یک فرمان دچار مشکل می‌شود، تمام دستورات دیگر در صف پردازش قرار می‌گیرند و Redis مانع پردازش دستورات نمی‌شود. که این موجب عدم رعایت Consistency یا سازگاری در اطلاعات می‌گردد.صرف نظر از صف دستوراتاز دستور DISCARD به منظور متوقف کردن تراکنش استفاده می‌شود. در این حالت، هیچ فرمانی اجرا نمی‌شود و وضعیت اتصال به ردیس به حالت عادی بازگردانده می­ شود :&gt; set x 1
    OK
 &gt; multi
    OK
 &gt; incr x
   QUEUED
&gt; discard
  OK
&gt; get x
  &amp;quot1&amp;quotعدم پشتیبانی Redis از Rollbackدر صورتی که تجربه کار با دیتابیس‌های رابطه ای را دارید، این که دستورات Redis می‌توانند در طول یک تراکنش دچار مشکل شوند، اما Redis به جای Rollback کردن آن‌ها، مابقی دستورات را اجرا می‌کند، ممکن است برای شما عجیب به نظر برسد.با این وجود دلایل خوبی برای این رفتار وجود دارد:• دستورات Redis فقط درصورتی می‌توانند موجب خطا شوند که با یک ساختار و Syntax اشتباه فراخوانی شوند یا دستورات فراخوانی شده برای دیتاتایپ کلید مورد نظر تعریف شده نباشد، مطابق آنچه که در خطاهای نوع دوم گفتیم. این مشکلات در حین افزودن دستور به صف قابل تشخیص نیست چون دستور اجرا نمی‌شود بلکه صف بندی می‌شود. بلکه پس از فراخوانی دستور EXEC ،وقتی نوبت اجرای دستور مشکل دار می‌رسد، خطا بر می گرداند.• Redis از نظر ساختار ساده‌تر و از لحاظ دسترسی سریع تر است به همین دلیل نیازی به Rollback ندارد.لذا با توجه به این دلایل، کنترل و مدیریت این خطاها بر عهده ی برنامه‌نویس گذاشته شده است.Redis - Scriptingاسکریپت Redis برای ارزیابی اسکریپت ها با استفاده از مفسر Lua استفاده می شود. از نسخه 2.6.0 در Redis ساخته شده است. دستور مورد استفاده برای اسکریپت نویسی دستور EVAL است.SyntaxFollowing is the basic syntax of EVAL command.redis 127.0.0.1:6379&gt; EVAL script numkeys key [key ...] arg [arg ...]ExampleFollowing example explains how Redis scripting works.redis 127.0.0.1:6379&gt; EVAL &amp;quotreturn {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}&amp;quot 2 key1 
key2 first second  
1) &amp;quotkey1&amp;quot 
2) &amp;quotkey2&amp;quot 
3) &amp;quotfirst&amp;quot 
4) &amp;quotsecond&amp;quot
Redis Scripting CommandsFollowing table lists some basic commands related to Redis Scripting.این مقاله اموزش هنوز تمام نشده است و درحین تهیه می باشد !!!با تشکر از مطالعه این مقاله، مثل همیشه کنجکاو باشید!!!در دوره های آموزش آنلاین تضمینی مجتمع فنی ارومیه که به صورت خصوصی و عمومی در دو شیوه حضوری و آنلاین برگزار می شود سرفصل های بسیار متنوع و کاربردی را بصورت پروژه محور آموزش داده می شود تا شخص کارآموز بتواند بلافاصله پس از اتمام این دوره در کمترین زمان ممکن وارد بازار کار شود.آموزش تخصص ماست با ما حرفه ای شویدجهت مشاوره با شماره 09149431772 در ارتباط باشید ... https://www.aparat.com/javadjahangiriniopdc/playlists </description>
                <category>جواد جهانگیری</category>
                <author>جواد جهانگیری</author>
                <pubDate>Fri, 26 Nov 2021 21:18:28 +0330</pubDate>
            </item>
                    <item>
                <title>ایجاد میکرو سرویس با C# asp.net core با  Redis</title>
                <link>https://virgool.io/@javadjahangiri/%D8%A7%DB%8C%D8%AC%D8%A7%D8%AF-%D9%85%DB%8C%DA%A9%D8%B1%D9%88-%D8%B3%D8%B1%D9%88%DB%8C%D8%B3-%D8%A8%D8%A7-c-aspnet-core-%D8%A8%D8%A7-%D8%AF%DB%8C%D8%AA%D8%A7%D8%A8%DB%8C%D8%B3-redis-fsez0rkeg0vg</link>
                <description>به نام آن که جان را فکرت آموخت / چراغ دل به نور جان برافروختدر این مقاله به آموزش نحوه ایجاد یک میکروسرویس (microservice) در C# asp.net core با دیتابیس ردیس (Redis) بصورت کاربردی و پروژه محور پرداخته می شود. منبع آموزشی استفاده شده در این سری مقاله ، آموزش های شرکت مایکروسافت در راستای معماری میکروسرویس و پروژه eShopOnContainers شرکت مایکروسافت و آموزش های استاد بزرگوار  Mehmet Özkaya در سایت udemy  می باشد . ایده این سری مقاله های آموزشی از این موضوع سرچشمه می گیرد که بخشی از خوانندگان وجود دارد که به محتوای نوشتاری آنلاین بهتر پاسخ می دهند و ترجیج می دهند مهارت های جدید را به سرعت از طریق خواندن افزایش دهند.این سری اموزش ها با ارایه اولین پکیج آموزشی در خصوص مانگودبی آغاز می شود که انتظار می رود با واکنش مثبت کاربران همراه شود.توجه: این مقاله به مرور زمان، ویرایش و یا تکمیل می‌شود! تقاضا: در صورتی که با مشکل تایپی، دستوری و یا مفهومی در این مقاله برخورد کردید، از شما دوست عزیز و گرامی، صمیمانه تقاضا می‌کنم که اینجانب را مطلع کرده، تا نسبت به تصحیح و یا تکمیل آن، در اسرع وقت، اقدام نمایم. با کمال تشکر جواد جهانگیری  شماره تلفن همراه: 09149431772 نشانی پست الکترونیکی: javad.jahangiri.niopdc@gmail.com فیلم‌های آموزشی در آپارات:جواد جهانگیری (CTO) - آپاراتفیلم آموزشی در یوتویب: javad jahangiri - YouTubeنسخه مقاله: 1.2 - تاریخ بروزرسانی: 1400/11/11پیشنهاد می شود قبل از این مطالعه این مقاله حتما ابتدا مقاله آموزش ایجاد میکرویس با C# asp.net core با دیتابیس mongo را مطالعه نمایید https://vrgl.ir/2S6vB در این مقاله آموزشی شروع به توسعه میکروسرویس سبد خرید (Basket) با دیتابیس Redis می کنیم که در شکل بالا نیز مشخص شده است با استفاده از C# asp.net core Web Api application بصورت RestApi یک پروژه ایجاد کرده و عملیات CRUD با استفاده از دیتابیس Redis با الگوی طراحی Repository با معماری چند لایه N-Layer   پیداسازی می کنیم و در نهایت این پروژه بر روی یک کانتینر پابلیش شده و  داکرایز می شود.Redisیک دیتابیس اوپن سورس از نوع NoSQL می باشدمخفف Remote Dictionary Server استبصورت جفت های key-value طراحی شده استیک Data Structure Server محسوب می شودفوق العاده سریع می باشدامکان ذخیره داده هم روی RAM و هم Disk را دارددارای امکانات تجاری از قبیل sharding , Cluster, Sentinel, Replication  می باشداگر بخواهیم بصورت حرفه ای بررسی کنیم تا این لحظه ن بصورت async کار نمی کند و بصورت (Single instance ) کار می کند و اجرای دستورات بصورت async در افزایش پرفورمانس آن زیاد تاثیر گذار نیستبا توجه به میزان اندازه داده ها به فضای رم نیازمند هستیدکوری های پیشرفته و پیچیده همانند دیتابیس های رابطه ای را پشتیبان نمی کند و در تراکنش ها (transaction) حالت Rollback را پشتیبانی نمی کند و اگر خطای رخ دهد بجای رول بک بقیه دستورات را اجرا می کند.نحوه نصب و راه اندازی Redis در Dockerوارد سایت docker hub مطابق شکل زیر می شویم و Redis را جستجو می کنیم و از نتایج نسخه official image را پیدا کرده و مطابق مستندات شروع به نصب می کنیممطابق اموزش های قبلی برنامه Docker Desktop را اجرا کرده وارد ترمینال ویندوز شده و ایمیج مربوط را pull می کنیمبعداز پول شده ایمیج می بایستی در لیست ایمیج های داکردسکتاپ ردیس اضافه شده باشد سپس از روی مستندات ایمیج Redis مطابق دستور زیر عمل می کنیمdocker run -d -p 6379:6379 --name aspnetrun-redis redisحالا می توانید از طریق دستور زیر چک کنید که Redis بدرستی اجرا شده استهمچنین می توانید از طریق Docker Desktop نیز اجرا شدن صحیح Redis مطمن شویدنحوه وارد شدن به Redis-cliاز طریق دستور زیر می توایند به محیط اینتر اکتیو مربوط به شل Redis وارد شوید:docker exec -it aspnetrun-redis /bin/bashسپس با وارد کردن Redis-cli وارد خط دستورات Redis می شویم و ادامه اموزش شروع به کار با دستورات Redis می کنیم ،همانطور که می دانید دیتابیس Redis بصورت جفت کلیدهای key/value کار می کند برای تست صحیح بودن عملیات یک کلید بنام name با مقدار javad ایجاد کرده و دوباره اطلاعات ان را به شرح ذیل می خوانیم:تحلیل و بررسی معماری میکروسرویس سبد خریددر این قسمت به بررسی معماری Basket Api Microservice پرداخته می شود در این پروژه Rest Api که قرار استفاده شود به شرح ذیل می باشد: معماری مربوط به لایه بندی پروژه به شرح ذیل می باشد:همانگونه که در اول اموزش نیز ذکر شد پیشنهاد می شود حتما قبل از شروع مطالعه این مقاله،مقاله  آموزش ایجاد میکرویس با C# asp.net core با دیتابیس mongo را مطالعه نمایید زیرا در حقیقت مقاله جاری پروژه دوم از پروژه eShopOnContainers شرکت مایکروسافت محسوب می شودو ساختار کلی پروژه نیز به شرح زیر می باشد:ناگت پکیج های مورد نیاز برای پروژه جاری را در زیر مشاهده می کنید :پکیج StackExchangeRedis برای ایجاد ارتباط با دیتابیس Redis استفاده می شود.برنامه نویسی میکروسرویس Basket.APIدر این قسمت شروع به برنامه نویسی میکروسرویس سبد خرید می کنیم دیتابیس این میکروسرویس را Redis انتخاب کردیم و این میکروسرویس برای مدیریت سبد خرید و ایتم های داخل سبد خرید و عملیات مربوط به ان می باشد و ایتم های سبد خرید در Redis کش می شوند دلیل اینکه ما در این پروژه از Redis برای کش استفاده کردیم به شرح زیر می باشد:distributed cacheکش های توزیع شده بصورت اشتراکی بوسیله چندین اپلیکیشن سرور  استفاده می شوند و بعنوان یک سرویس می باشد که سایر اپلیکشن ها می تواند از ان استفاده نمایند و همچنین کش توزیع شده باعث افزایش پرفورمانش و مقایس پذیری پروژه های asp.net core می شود علی الخصوص در مواقعی که بر روی فضای ابری قرار می گیرد و یا روی سرور فارم ها استفاده می شودیک پروژه asp.net core web api بصورت زیر ایجاد می کنیم:بر روی گزینه create and push کلیک می کنید و بر روی گیت هاب یک مخزن با نام مذکور ایجاد می شود و سورس های پروژه در ان Push می شود https://github.com/javadjahangiriniopdc/BasketApiwithRedis در اولین مرحله نسبت به حذف کنترلر آب و هوا و موجودیت آن اقدام می کنیدپوشه Entities را به پروژه اضافه می کنید و به ترتیب موجودیت های ShoppingCartItem و ShoppingCart به شرح ذیل به پروژه اضافه می کنیمnamespace BasketApiwithRedis.Entities
{
    public class ShoppingCartItem
    {
        public int Quantity { get; set; }
        public string Color { get; set; }
        public decimal Price { get; set; }
        public string ProductId { get; set; }
        public string ProductName { get; set; }
    }
}using System;
using System.Collections.Generic;

namespace BasketApiwithRedis.Entities
{
    public class ShoppingCart
    {
        public string UserName { get; set; }
        public List&lt;ShoppingCartItem&gt; Items { get; set; } = new List&lt;ShoppingCartItem&gt;();

        public ShoppingCart()
        {

        }

        public ShoppingCart(string username)
        {
            this.UserName = username;
        }

        public decimal TotalPrice
        {
            get
            {
                decimal totalprice = 0;
                foreach (var item in Items)
                {
                    totalprice += item.Price * item.Quantity;
                }
                return totalprice;
            }
        }
    }
}نسبت به نصب پکیج Microsoft.Extensions.Caching.StackExchangeRedis در پروژه برای ارتباط با دیتابیس Redis به شرح زیر عمل می کنیم:نحوه ایجاد کانکشن به دیتابیس Redisابتدا تنظیمات مربوط به کانکشن استرینگ به فایل appsetting.json به شرح ذیل اضافه می کنیدسپس به فایل استارت اپ پروژه بصورت ذیل سرویس AddStackExchangeRedisCache بصورت ذیل تنظیم می کنیم:کد زیر به ConfigServices اضافه می کنید: // Redis Configuration
   services.AddStackExchangeRedisCache(options =&gt;
            {
    options.Configuration = Configuration.GetValue&lt;string&gt;(&amp;quotCacheSettings:ConnectionString&amp;quot);
            });برنامه نویسی Repository Pattern در این قسمت به برنامه و توسعه دیزاین پترن ریپوزیتوری در میکروسرویس سبد خرید می پردازیم برای این کار یک پوشه بنام Repositories را به پروژه اضافه کرده و یک اینترفیس IBasketRepository به این پوشه اضافه می کنیم و در ادامه ان نیز با کلاس BasketRepository که  اینترفیس مذکور را پیاده سازی می کنیمusing BasketApiwithRedis.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace BasketApiwithRedis.Repositories
{
    public interface IBasketRepository
    {
        Task&lt;ShoppingCart&gt; GetBasket(string userName);
        Task&lt;ShoppingCart&gt; UpdateBasket(ShoppingCart basket);
        Task DeleteBasket(string userName);
    }
}توجه شود قبلا از ایجاد کلاس حتما Newtonsoft.Json را توسط PMC نصب شودusing BasketApiwithRedis.Entities;
using Microsoft.Extensions.Caching.Distributed;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace BasketApiwithRedis.Repositories
{
    public class BasketRepository : IBasketRepository
    {
        private readonly IDistributedCache _redisCache;

        public BasketRepository(IDistributedCache cache)
        {
            _redisCache = cache ?? throw new ArgumentNullException(nameof(cache));
        }

        public async Task&lt;ShoppingCart&gt; GetBasket(string userName)
        {
            var basket = await _redisCache.GetStringAsync(userName);

            if (String.IsNullOrEmpty(basket))
                return null;

            return JsonConvert.DeserializeObject&lt;ShoppingCart&gt;(basket);
        }

        public async Task&lt;ShoppingCart&gt; UpdateBasket(ShoppingCart basket)
        {
            await _redisCache.SetStringAsync(basket.UserName, JsonConvert.SerializeObject(basket));

            return await GetBasket(basket.UserName);
        }

        public async Task DeleteBasket(string userName)
        {
            await _redisCache.RemoveAsync(userName);
        }

    }
}
و درنهایت پروژه را کامپایل می کنیمبرنامه نویسی  کنترلربه پروژه یک پوشه بنام Controllers اضافه می کنیم و به ان یک کنترلر بنام BasketController اضافه می کنیمusing BasketApiwithRedis.Entities;
using BasketApiwithRedis.Repositories;
using Microsoft.AspNetCore.Mvc;
using System.Net;
using System.Threading.Tasks;
namespace BasketApiwithRedis.Controllers
{
    [ApiController]
    [Route(&amp;quotapi/v1/[controller]&amp;quot)]
    public class BasketController:ControllerBase
    {
        private readonly IBasketRepository _repositroy;
        public BasketController(IBasketRepository repositroy)
        {
            _repositroy = repositroy;
        }
        [HttpGet(&amp;quot{userName}&amp;quot,Name =&amp;quotGetBasket&amp;quot)]
        [ProducesResponseType(typeof(ShoppingCart),(int) HttpStatusCode.OK)]
        public async Task&lt;ActionResult&lt;ShoppingCart&gt;&gt; GetBasket(string userName)
        {
            var basket=await _repositroy.GetBasket(userName);
            return Ok(basket ??  new ShoppingCart(userName));
        }
        [HttpPost]
        [ProducesResponseType(typeof(ShoppingCart),(int)HttpStatusCode.OK)]
        public async Task&lt;ActionResult&lt;ShoppingCart&gt;&gt; UpdateBasket([FromBody] ShoppingCart basket)
        {
            return Ok(await _repositroy.UpdateBasket(basket));
        }
        [HttpDelete(&amp;quot{userName}&amp;quot,Name =&amp;quotDeleteBasket&amp;quot)]
        [ProducesResponseType(typeof(void), (int)HttpStatusCode.OK)]
        public async Task&lt;IActionResult&gt; DeleteBasket(string userName)
        {
            await _repositroy.DeleteBasket(userName);
            return Ok();
        }
    } 
}درنهایت در فایل Startup.Cs می بایستی IBasketRepository را رجیستر می کنیم :  services.AddScoped&lt;IBasketRepository, BasketRepository&gt;();تست و اجرای میکروسرویسوارد ترمینال برنامه می شویم :مطمن می شویم که کانتنر مربوط به Redis بالا بوده و با پورت 6379 در حال سرویس می باشد و سپس پروژه را اجرا می گیریم و خروجی به شکل زیر قابل مشاهده می باشد:حال برای تست api اول به شرح ذیل عمل می کنیم :ومی بایستی خروجی به شکل زیر دریافت کنید:حالا برای درج اطلاعات در سبد خرید به شرح زیر عمل می کنیم:{  &amp;quotuserName&amp;quot: &amp;quotswm&amp;quot,
  &amp;quotitems&amp;quot: [
    {
      &amp;quotquantity&amp;quot: 1,
      &amp;quotcolor&amp;quot: &amp;quotwhite&amp;quot,
      &amp;quotprice&amp;quot:950,
      &amp;quotproductId&amp;quot: &amp;quot602d2149e773f2a3990b47f5&amp;quot,
      &amp;quotproductName&amp;quot: &amp;quotIPhone X&amp;quot
    },
 {
      &amp;quotquantity&amp;quot: 2,
      &amp;quotcolor&amp;quot: &amp;quotwhite&amp;quot,
      &amp;quotprice&amp;quot:840,
      &amp;quotproductId&amp;quot: &amp;quot602d2149e773f2a3990b47f6&amp;quot,
      &amp;quotproductName&amp;quot: &amp;quotSamsung 10&amp;quot
    }
  ]
}توجه شود کد محصولاتی که در این قسمت وارد می شود یکی از محصولاتی باشد که در مقاله آموزش ایجاد میکروسرویس با C# asp.net core با دیتابیس MongoDB در قسمت Seed داده های استفاده شده است https://vrgl.ir/2S6vB این مقاله اموزش هنوز تمام نشده است و درحین تهیه می باشد !!!باتشکر از مطالعه این مقاله ,مثل همیشه کنجکاو باشید!!!در دوره های آموزش تضمینی مجتمع فنی ارومیه که به صورت خصوصی و عمومی در دو شیوه حضوری و آنلاین برگزار می شود سرفصل های بسیار متنوع و کاربردی را بصورت پروژه محور آموزش داده می شود تا شخص کارآموز بتواند بلافاصله پس از اتمام این دوره در کمترین زمان ممکن وارد بازار کار شود.آموزش تخصص ماست با ما حرفه ای شویدجهت مشاوره با شماره 09149431772 در ارتباط باشید ... https://www.aparat.com/javadjahangiriniopdc/playlists </description>
                <category>جواد جهانگیری</category>
                <author>جواد جهانگیری</author>
                <pubDate>Fri, 12 Nov 2021 12:23:32 +0330</pubDate>
            </item>
                    <item>
                <title>آموزش ایجاد میکروسرویس با C# asp.net core با دیتابیس MongoDB</title>
                <link>https://virgool.io/@javadjahangiri/%D8%A7%DB%8C%D8%AC%D8%A7%D8%AF-%DB%8C%DA%A9-%D9%85%DB%8C%DA%A9%D8%B1%D9%88%D8%B3%D8%B1%D9%88%DB%8C%D8%B3-%D8%A8%D8%A7-c-aspnet-core-%D8%A8%D8%A7-%D8%AF%DB%8C%D8%AA%D8%A7%D8%A8%DB%8C%D8%B3-mongodb-cbomtc1daxpi</link>
                <description> به نام آن که جان را فکرت آموخت / چراغ دل به نور جان برافروختدر این مقاله از سری مقاله های آموزشی مونگودبی به آموزش نحوه ایجاد یک میکروسرویس (microservice) در C# asp.net core  با دیتابیس مونگودبی (mongoDb) بصورت کاربردی و پروژه محور پرداخته می شود. منبع آموزشی استفاده شده در این سری مقاله ها ، آموزش های شرکت مایکروسافت در راستای معماری میکروسرویس و پروژه  eShopOnContainers شرکت مایکروسافت و و آموزش های استاد بزرگوار Mehmet Özkaya در سایت udemy می باشد.  ایده این سری مقاله های آموزشی از این موضوع سرچشمه می گیرد که بخشی از خوانندگان وجود دارد که به محتوای نوشتاری آنلاین بهتر پاسخ می دهند و ترجیج می دهند مهارت های جدید را به سرعت از طریق خواندن افزایش دهند.این سری اموزش ها با ارایه اولین پکیج آموزشی در خصوص مانگودبی آغاز می شود که انتظار می رود با واکنش مثبت کاربران همراه شود.Microservices Using ASP.NET Core, MongoDBتوجه: این مقاله به مرور زمان، ویرایش و یا تکمیل می‌شود! تقاضا: در صورتی که با مشکل تایپی، دستوری و یا مفهومی در این مقاله برخورد کردید، از شما دوست عزیز و گرامی، صمیمانه تقاضا می‌کنم که اینجانب را مطلع کرده، تا نسبت به تصحیح و یا تکمیل آن، در اسرع وقت، اقدام نمایم. با کمال تشکر جواد جهانگیری  شماره تلفن همراه: 09149431772 نشانی پست الکترونیکی: javad.jahangiri.niopdc@gmail.com فیلم‌های آموزشی در آپارات:جواد جهانگیری (CTO) - آپاراتفیلم آموزشی در یوتویب: javad jahangiri - YouTubeنسخه مقاله: ۱.۱ - تاریخ بروزرسانی: 1400/09/09  https://www.aparat.com/javadjahangiriniopdc/playlists ما در این مقاله اموزشی  یک میکروسرویس در C# asp.net core بصورت web api براساس RestApi ایجاد می کنیم و  عملیات CRUD بر روی product و Category با دیتابیس mongdb را خواهیم داشت و  پیاده سازی بصورت Repository Pattern  خواهد بود و از swagger برای Open Api استفاده می کنیم ,معماری  استفاده شده بصورت architecture  N-Layer می باشد  و در نهایت میکروسرویس ایجاد شده بر روی Docker پابلیش خواهد شدبرای دسترسی به سورس های این پروژه می توانید وارد github بنده به ادرس javad.jahangiri.niopdc زیر شوید: https://github.com/javadjahangiriniopdc برای این مقاله آموزشی یک ریپوزیتوری بنام MicroservicesUsingASP.NETCoreMongoDB ایجاد شده و سورس ها در این مخزن push  می شودابتدا نسبت به ایجاد یک پروژه ASP.NET Core Web Api مطابق تصاویر زیر به ترتیب اقدام می کنید بر روی گزینه create and push کلیک می کنید و بر روی گیت هاب یک مخزن با نام مذکور ایجاد می شود و سورس های پروژه در ان Push می شودپیش نیازهای این آموزشپیشنهاد می شود قبل از شروع به مطالعه این مقاله نسبت به مطالعه مقالات ذیل اقدام نمایید  https://virgool.io/@javadjahangiri/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%D8%AF%DB%8C%D8%AA%D8%A7%D8%A8%DB%8C%D8%B3-%D9%85%D9%88%D9%86%DA%AF%D9%88%D8%AF%D8%A8%DB%8C-mongodb-tutorial-incadc7thvtl  https://virgool.io/@javadjahangiri/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-mongodbcompass-%D8%AF%D8%B1-%D9%85%D9%88%D9%86%DA%AF%D9%88%D8%AF%D8%A8%DB%8C-ffdeooxnhrpy نصب Docker Desktopبا عنایت به اینکه در این آموزش قصد داریم درنهایت پروژه را بر روی داکر پابلیش کنیم لذا می بایستی ابتدا بر روی سیستم عامل ویندوز داکر رو نصب کنیم برای این کار راحترین روش استفاده از Docker Desktop می باشد ابتدا وارد سایت زیر شده و برنامه داکر دسکتاب را دانلود و نصب می کنید https://www.docker.com/products/docker-desktop و وارد برنامه داکر دسکتاب می شویم:سپس وارد سایت داکرهاب می شویم تا image مربوط به مونگودبی را پیدا کنیم https://hub.docker.com/_/mongo معمولا از نسخه رسمی Official Image استفاده می کنیم:سپس وارد محیط ویژال استادیو خودمان می شویم بر روی Solution راست کلیک کرده و گزینه open terminal کلیک می کنیم:تا پنجره پاور شل برای ما باز شود:حال از طریق کد زیر چک می کنیم که داکر بر روی سیستم عامل ما نصب و فعال می باشدdocker psاز طریق کد زیر ایمیج مربوط به مونگودبی روی کامپیوتر خودمان pull می کنیم:docker pull mongo
نکته:دقت شود از آنجایی که اگر مونگودبی در ویندوز نصب شده باشد و سرویس ان فعال باشد پورت 27017 در حال استفاده است دستور اجرای داکر خطا می دهد لذا ابتدا از سرویس های ویندوز سرویس مانگودبی را stop کنید سپس از اقدام به اجرای داکر مونگودبی نماییدسپس از طریق کد زیر ایمیج مونگودبی را بر روی داکر اجرا می کنیمdocker run -d -p 27017:27017 --name store-mongo mongoاز طریق کد زیر چک می کنیم که کانتنر مونگودبی اجرا شده است:docker psاز طریق دستور زیر می توانیم لاک کانتنر مونگودبی را مشاهده کنید برای خروج از حالت نمایش لاگ کلیدهای ترکیبی Ctrl+C را استفاده کنید:docker logs -f store-mongoاز طریق دستور ذیل می توانیم وارد خط فرمان کانتنر بصورت  اینتراکتیور مونگودبی بشوید:docker exec -it store-mongo /bin/bashسپس می توانید بصورت اینتر اکتیو mongo را اجرا کنید:حالا که وارد محیط مونگودبی شل شدیم می توانید دستوارت مونگودبی را وارد نمایید برای مثال مشاهده دیتابیس ها:show dbsایجاد دیتابیس StoreDb:use StoreDbایجاد کالکشن (جدول) Products:db.createCollection(&#039;Products&#039;)درج سند (رکورد) در کالکشن (جدول) محصولات:db.Products.insertMany([{ &#039;Name&#039;:&#039;Asus Laptop&#039;,&#039;Category&#039;:&#039;Computers&#039;, &#039;Summary&#039;:&#039;Summary&#039;, &#039;Description&#039;:&#039;Description&#039;, &#039;ImageFile&#039;:&#039;ImageFile&#039;, &#039;Price&#039;:54.93 }, { &#039;Name&#039;:&#039;HP Laptop&#039;,&#039;Category&#039;:&#039;Computers&#039;, &#039;Summary&#039;:&#039;Summary&#039;, &#039;Description&#039;:&#039;Description&#039;, &#039;ImageFile&#039;:&#039;ImageFile&#039;, &#039;Price&#039;:88.93 } ])برای نمایش اطلاعات درج شده می تواند از دستور find بهمراه اپراتور pretty استفاده کرد:db.Products.find({}).pretty()آنالیز و معماری میکروسرویس Storeدر این مقاله اموزشی ما قصد داریم یک میکرسرویس بنام Store با شرایط ذیل ایجاد کنیم: ASP.NET Core Web API applicationREST API principles, CRUD operationsMongoDB database connection and containerizationRepository Pattern ImplementationContainerize Store Microservices with MongoDb using Docker Composeرست ای پی آی مربوط به میکرسرویس فروشگاه:معماری لایه ای میکروسرویس فروشگاه:Store Layered Architecturesپکیج ها ناگت مورد نیاز برای این پروژه:MongoDb.DriverSwashBuckle.AspNetCoreالگوی طراحی Repository Design Pattern چیست؟از repository برای جلوگیری از دوباره کاری و تکرار استفاده می شود. امروزه در پروژه های حرفه ای که با معماری multi-tier یا multi-layer ایجاد می شوند، لازم است که از دوباره کاری پرهیز شود.الگوی Repository:گاهی اوقات لازم است یک منطق بین منطق کاری و منطق دسترسی داده ها تعریف شود. این منطق می تواند استفاده کردن از الگوی Repository  را تعریف کند.  اساسایک میانجی بین دو لایه است. عمدتا جایی استفاده می شود که نیاز است داده ها قبل از رفتن به مرحله بعد تغییر کنند.مزایای استفاده از Repository:. متمرکز کردن منطق داده ها (data logic) یا منطق کاری (business logic)و منطق سرویس (service logic)یک  نقطه تعویض برای واحد تست است.یک معماری قابل انعطاف فراهم میکند.اگر بخواهید منطق دسترسی داده ها یا منطق کاری را تغییر دهید نیازی نیست منطق repository را تغییر دهید.الگوی Generic repository:گاهی اوقات لازم است یا بهتر است همه منطق های repository در یک مکان با استفاده از generic logic ساخته شوند. ما می توانیم فقط یک کلاسrepository ایجاد کنیم که مسئول رسیدگی به کل سناریو خواهد بود. می تواند یک منطق بین repository و دسترسی به داده ها  یا یک منطق بین منطق کاری و repository باشد. در همه موارد ما فقط یک repository می نویسیم. مزیت اصلی generic repository ، استفاده مجدد از کد است.مزایای استفاده از Generic repository: افزونگی کد را کاهش می دهد.برنامه نویس را به استفاده از همان الگو مجبور میکند.ایجاد خطاها را کمتر می کند.اگر از این الگو استفاده کنید ، نگه داری منطق دسترسی به داده های متمرکز آسان می شود.حذف WeatherForecast از پروژه :از انجایی که پروژه از روی api template مایکروسافت ایجاد شده است شامل api مربوط به آب و هوا می باشد که باید از پروژه حذف شود برای این کار فایل های زیر از پروژه حدف می کنیم:نصب پکیج ها ی مورد نیاز پروژه :وارد NuGet Package Manager  می شویم وارد در tab مربوط به Brows ابتدا mongoDb.Driver را جستجو و نصب می کنیم:روش دیگر نصب پکیج های مورد نیاز استفاده از PMC (Package Manager Console) می باشد ابتدا وارد سایت nuget شده و عبارت mongoDb را جستجو کرده و از لیست پکیج ها MongoDB.Driver را انتخاب می کنیم :سپس وارد محیط PMC  و دستور زیر را که از سایت کپی کردیم وارد می کنیم :Install-Package MongoDB.Driver -Version 2.14.0-beta1اضافه کردن Entity های پروژه:ابتدا یه پوشه به پروژه بنام Entities اضافه می کنیم:یک کلاس بنام Product به این پوشه اضافه می کنیم:public class Product
    {
        [BsonId]
        [BsonRepresentation(BsonType.ObjectId)]
        public string Id { get; set; }
        [BsonElement(&amp;quotName&amp;quot)]
        public string Name { get; set; }
        public string Category { get; set; }
        public string Summary { get; set; }
        public string Description { get; set; }
        public string ImageFile { get; set; }
        public decimal Price { get; set; }
    }Product.Csاضافه کردن کانکشن دیتابیس مونگودبی به پروژه:داخل فایل appsetting.json  شده و تنظیمات ذیل را به آن اضافه می کنید:&amp;quotDatabaseSettings&amp;quot:{
&amp;quotConnectionString&amp;quot: &amp;quotmongodb://localhost:27017&amp;quot,
&amp;quotDatabaseName&amp;quot: &amp;quotStoreDb&amp;quot,
&amp;quotCollectionName&amp;quot: &amp;quotProducts&amp;quot
 },برنامه نویسی Data Layer  پروژه:برای این کار یک پوشه بنام Data به پروژه اضافه کنید و اینترفیس IStoreContext را به ان پوشه اضافه می کنیم:public interface IStoreContext     {       
   IMongoCollection&lt;Product&gt; Products { get;  }   
  }یک فایل کلاس بنام StoreContextSeed برای Seed داده های اولیه به پوشه Data اضافه می کنیم:using MongoDB.Driver;
using System.Collections.Generic;
using System.Linq;
namespace MicroservicesUsingASP.NETCoreMongoDB.Data
{
    public class StoreContextSeed
    {
        public static void SeedData(IMongoCollection&lt;Product&gt; productCollection)
        {
            bool existProduct = productCollection.Find(p =&gt; true).Any();
            if (!existProduct)
            {
                productCollection.InsertManyAsync(GetPreconfiguredProducts());
            }
        }
        private static IEnumerable&lt;Product&gt; GetPreconfiguredProducts()
        {
            return new List&lt;Product&gt;()
            {
                new Product()
                {
                    Id = &amp;quot602d2149e773f2a3990b47f5&amp;quot,
                    Name = &amp;quotIPhone X&amp;quot,
                    Summary = &amp;quotThis phone is the company&#039;s biggest change to its flagship smartphone in years. It includes a borderless.&amp;quot,
                    Description = &amp;quotLorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus.&amp;quot,
                    ImageFile = &amp;quotproduct-1.png&amp;quot,
                    Price = 950.00M,
                    Category = &amp;quotSmart Phone&amp;quot
                },
                new Product()
                {
                    Id = &amp;quot602d2149e773f2a3990b47f6&amp;quot,
                    Name = &amp;quotSamsung 10&amp;quot,
                    Summary = &amp;quotThis phone is the company&#039;s biggest change to its flagship smartphone in years. It includes a borderless.&amp;quot,
                    Description = &amp;quotLorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus.&amp;quot,
                    ImageFile = &amp;quotproduct-2.png&amp;quot,
                    Price = 840.00M,
                    Category = &amp;quotSmart Phone&amp;quot
                },
                new Product()
                {
                    Id = &amp;quot602d2149e773f2a3990b47f7&amp;quot,
                    Name = &amp;quotHuawei Plus&amp;quot,
                    Summary = &amp;quotThis phone is the company&#039;s biggest change to its flagship smartphone in years. It includes a borderless.&amp;quot,
                    Description = &amp;quotLorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus.&amp;quot,
                    ImageFile = &amp;quotproduct-3.png&amp;quot,
                    Price = 650.00M,
                    Category = &amp;quotWhite Appliances&amp;quot
                },
                new Product()
                {
                    Id = &amp;quot602d2149e773f2a3990b47f8&amp;quot,
                    Name = &amp;quotXiaomi Mi 9&amp;quot,
                    Summary = &amp;quotThis phone is the company&#039;s biggest change to its flagship smartphone in years. It includes a borderless.&amp;quot,
                    Description = &amp;quotLorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus.&amp;quot,
                    ImageFile = &amp;quotproduct-4.png&amp;quot,
                    Price = 470.00M,
                    Category = &amp;quotWhite Appliances&amp;quot
                },
                new Product()
                {
                    Id = &amp;quot602d2149e773f2a3990b47f9&amp;quot,
                    Name = &amp;quotHTC U11+ Plus&amp;quot,
                    Summary = &amp;quotThis phone is the company&#039;s biggest change to its flagship smartphone in years. It includes a borderless.&amp;quot,
                    Description = &amp;quotLorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus.&amp;quot,
                    ImageFile = &amp;quotproduct-5.png&amp;quot,
                    Price = 380.00M,
                    Category = &amp;quotSmart Phone&amp;quot
                },
                new Product()
                {
                    Id = &amp;quot602d2149e773f2a3990b47fa&amp;quot,
                    Name = &amp;quotLG G7 ThinQ&amp;quot,
                    Summary = &amp;quotThis phone is the company&#039;s biggest change to its flagship smartphone in years. It includes a borderless.&amp;quot,
                    Description = &amp;quotLorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus.&amp;quot,
                    ImageFile = &amp;quotproduct-6.png&amp;quot,
                    Price = 240.00M,
            Category = &amp;quotHome Kitchen&amp;quot
         }
         };
       }
    }
}یک فایل StoreContext.Cs به پوشه Data اضافه می کنید که از اینترفیس IStoreContext ارثبری کند:using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MicroservicesUsingASP.NETCoreMongoDB.Entities;
using Microsoft.Extensions.Configuration;
using MongoDB.Driver;
using MongoDB.Driver.Core.Operations;
namespace MicroservicesUsingASP.NETCoreMongoDB.Data
{
    public class StoreContext :IStoreContext
    {
        public StoreContext(IConfiguration configuration)
        {
            var client = new MongoClient(configuration.GetValue&lt;string&gt;(&amp;quotDatabaseSettings:ConnectionString&amp;quot));
            var database = client.GetDatabase(configuration.GetValue&lt;string&gt;(&amp;quotDatabaseSettings:DatabaseName&amp;quot));
            Products = database.GetCollection&lt;Product&gt;(configuration.GetValue&lt;string
(&amp;quotDatabaseSettings:CollectionName&amp;quot));
            StoreContextSeed.SeedData(Products);
        }
        public IMongoCollection&lt;Product&gt; Products { get; }
    }
}Data Layerبرنامه نویسی Business Layer  پروژه:یک پوشه Repositories به پروژه اضافه می کنیم و یک اینترفیس IProductRepository به پوشه Repositories اضافه می کنیم:using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MicroservicesUsingASP.NETCoreMongoDB.Entities;
namespace MicroservicesUsingASP.NETCoreMongoDB.Repositories
{
    public interface IProductRepository
    {
        Task&lt;IEnumerable&lt;Product&gt;&gt; GetProducts();
        Task&lt;Product&gt; GetProduct(string id);
        Task&lt;IEnumerable&lt;Product&gt;&gt; GetProductByName(string name);
        Task&lt;IEnumerable&lt;Product&gt;&gt; GetProductByCategory(string categoryName);
        Task CreateProduct(Product product);
        Task&lt;bool&gt; UpdateProduct(Product product);
        Task&lt;bool&gt; DeleteProduct(string id);
    }
}یک کلاس بنام ProductRepository که از IProductRepository ارث بری کند به پروژه اضافه می کنیم و توابع مورد نیاز را پیاده سازی می کند:using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MicroservicesUsingASP.NETCoreMongoDB.Data;
using MicroservicesUsingASP.NETCoreMongoDB.Entities;
using MongoDB.Driver;
namespace MicroservicesUsingASP.NETCoreMongoDB.Repositories{
    public class ProductRepository : IProductRepository
    {
        private readonly IStoreContext _context;
        public ProductRepository(IStoreContext context)
        {            _context = context ?? throw new ArgumentNullException(nameof(context));
        }
        public async Task&lt;IEnumerable&lt;Product&gt;&gt; GetProducts()
        {
            return await _context
                .Products
                .Find(p =&gt; true)
                .ToListAsync();
        }
        public async Task&lt;Product&gt; GetProduct(string id)
        {
            return await _context
                .Products
                .Find(p =&gt; p.Id == id)
                .FirstOrDefaultAsync();
        }
        public async Task&lt;IEnumerable&lt;Product&gt;&gt; GetProductByName(string name)
        {
            FilterDefinition&lt;Product&gt; filter = Builders&lt;Product&gt;.Filter.ElemMatch(p =&gt; p.Name, name);
            return await _context
               .Products
                .Find(filter)
                .ToListAsync();
        }
        public async Task&lt;IEnumerable&lt;Product&gt;&gt; GetProductByCategory(string categoryName)
        {
            FilterDefinition&lt;Product&gt; filter = Builders&lt;Product&gt;.Filter.Eq(p =&gt; p.Category, categoryName);
            return await _context
                .Products
                .Find(filter)
                .ToListAsync();
        }
        public async Task CreateProduct(Product product)
        {
            await _context.Products.InsertOneAsync(product);
        }
        public async Task&lt;bool&gt; UpdateProduct(Product product)
        {
            var updateResult = await _context
                .Products
                .ReplaceOneAsync(filter: g =&gt; g.Id == product.Id, replacement: product);
            return updateResult.IsAcknowledged
                   &amp;&amp; updateResult.ModifiedCount &gt; 0;
        }
        public async Task&lt;bool&gt; DeleteProduct(string id)
        {
            FilterDefinition&lt;Product&gt; filter = Builders&lt;Product&gt;.Filter.Eq(p =&gt; p.Id, id);            DeleteResult deleteResult = await _context
                .Products
                .DeleteOneAsync(filter);
            return deleteResult.IsAcknowledged
                   &amp;&amp; deleteResult.DeletedCount &gt; 0;
        }
    }
}برنامه نویسی Presentation Layer پروژه:کلاس StoreController را به پوشه Controller اضافه می کنیم دقت شود که نوع این کنترلر باید به Api تبدیل شود و روتینگ api/v1 به ان اضافه شود و از ControllerBase ارث بری داشته باشد:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using MicroservicesUsingASP.NETCoreMongoDB.Entities;
using MicroservicesUsingASP.NETCoreMongoDB.Repositories;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

namespace MicroservicesUsingASP.NETCoreMongoDB.Controllers
{
    [ApiController]
    [Route(&amp;quotapi/v1/[controller]&amp;quot)]
    public class StoreController:ControllerBase
    {
        private readonly IProductRepository _repository;
        private readonly ILogger&lt;StoreController&gt; _logger;

        public StoreController(IProductRepository repository, ILogger&lt;StoreController&gt; logger)
        {
            _repository = repository;
            _logger = logger;
        }

        [HttpGet]
        [ProducesResponseType(typeof(IEnumerable&lt;Product&gt;), (int)HttpStatusCode.OK)]
        public async Task&lt;ActionResult&lt;IEnumerable&lt;Product&gt;&gt;&gt; GetProducts()
        {
            var products = await _repository.GetProducts();
            return Ok(products);
        }


        [HttpGet(&amp;quot{id:length(24)}&amp;quot, Name = &amp;quotGetProduct&amp;quot)]
        [ProducesResponseType((int)HttpStatusCode.NotFound)]
        [ProducesResponseType(typeof(Product), (int)HttpStatusCode.OK)]
        public async Task&lt;ActionResult&lt;Product&gt;&gt; GetProductById(string id)
        {
            var product = await _repository.GetProduct(id);

            if (product == null)
            {
                _logger.LogError($&amp;quotProduct with id: {id}, not found.&amp;quot);
                return NotFound();
            }

            return Ok(product);
        }


        [Route(&amp;quot[action]/{category}&amp;quot, Name = &amp;quotGetProductByCategory&amp;quot)]
        [HttpGet]
        [ProducesResponseType(typeof(IEnumerable&lt;Product&gt;), (int)HttpStatusCode.OK)]
        public async Task&lt;ActionResult&lt;IEnumerable&lt;Product&gt;&gt;&gt; GetProductByCategory(string category)
        {
            var products = await _repository.GetProductByCategory(category);
            return Ok(products);
        }

        [Route(&amp;quot[action]/{name}&amp;quot, Name = &amp;quotGetProductByName&amp;quot)]
        [HttpGet]
        [ProducesResponseType((int)HttpStatusCode.NotFound)]
        [ProducesResponseType(typeof(IEnumerable&lt;Product&gt;), (int)HttpStatusCode.OK)]
        public async Task&lt;ActionResult&lt;IEnumerable&lt;Product&gt;&gt;&gt; GetProductByName(string name)
        {
            var items = await _repository.GetProductByName(name);
            if (items == null)
            {
                _logger.LogError($&amp;quotProducts with name: {name} not found.&amp;quot);
                return NotFound();
            }
            return Ok(items);
        }

        [HttpPost]
        [ProducesResponseType(typeof(Product), (int)HttpStatusCode.OK)]
        public async Task&lt;ActionResult&lt;Product&gt;&gt; CreateProduct([FromBody] Product product)
        {
            await _repository.CreateProduct(product);

            return CreatedAtRoute(&amp;quotGetProduct&amp;quot, new { id = product.Id }, product);
        }

        [HttpPut]
        [ProducesResponseType(typeof(Product), (int)HttpStatusCode.OK)]
        public async Task&lt;IActionResult&gt; UpdateProduct([FromBody] Product product)
        {
            return Ok(await _repository.UpdateProduct(product));
        }

        [HttpDelete(&amp;quot{id:length(24)}&amp;quot, Name = &amp;quotDeleteProduct&amp;quot)]
        [ProducesResponseType(typeof(Product), (int)HttpStatusCode.OK)]
        public async Task&lt;IActionResult&gt; DeleteProductById(string id)
        {
            return Ok(await _repository.DeleteProduct(id));
        }
    }
}رجیستر کردن کلاس های  StoreContext و ProductRepository  برای این کار وارد فایل Startup پروژه می شویم و به  متد ConfigureServices  رفته و کدهای زیر را به ان اضافه می کنیم: public void ConfigureServices(IServiceCollection services)
        {
            services.AddScoped&lt;IStoreContext, StoreContext&gt;();
            services.AddScoped&lt;IProductRepository, ProductRepository&gt;();
            services.AddControllers();
            services.AddSwaggerGen(c =&gt;
            {
                c.SwaggerDoc(&amp;quotv1&amp;quot, new OpenApiInfo { Title = &amp;quotMicroservicesUsingASP.NETCoreMongoDB&amp;quot, Version = &amp;quotv1&amp;quot });
            });
        }در اخر این مرحله یکبار پروژه را Build میگریم که خطای وجود نداشته باشد:تست و اجرای پروژهبرای تست پروژه ابتدا مطمن شوید که داکر دسکتاب اجرا شده و کانتینر مونگودبی فعال می باشداگر کانتینر مونگودبی در حین اجرا نبود با روش بالا کانتینر را استارت می کنیم:روش دیگری که می شود چک کنیم استفاده از ترمینال به شرح ذیل می باشدتنظیمات دیباگ پروژه رو مطابق تصویر زیر انجام دهید:سپس پروژه به شکل ذیل اجرا می کنیم:برنامه به شکل ذیل اجرا می شود:درنهایت خروجی پروژه در swagger به شکل ذیل نمایش داده می شود:اجرای Web Api مربوط به GetProductنحوه اجرای متد get برای نمایش اطلاعات محصولات به شرح ذیل عمل می کنید:بر روی گزینه Try it out کلیکد کنید تا کلید execute نمایش داده شود :باکلیک با روی گزینه execute درخواست به web api مربوطه ارسال شده و نتیجه نمایش داده می شود با عنایت به اینکه برای پروژه Seed تعریف شده بود دو رکوردی که در مرحله اول اجرا پروژه درج شده بودند نمایش داده می شود:اجرای Api مربوط به GetProductByNameاین وب ای پی آی برای فیلتر کردن محصولات براساس نام محصولات به شرح ذیل می باشد:نحوه تست web api با استفاده از postmanابتدا وارد نرم افزار postman شده یک Collection اضافه می کنید بنام MicroservicesUsingASP.NETCoreMongoDB می کنیم و سپس یک درخواست از نوع get با نام  GetProducts ایجاد می کنیم با درخواست http://localhost:5000/api/v1/Store ایجاد می کنیم و در نهایت بر روی گزینه send کلیک می کنیم نحوه فراخوانی GetProductByCategory از طریق Postman:در این قسمت می خواهیم web api مربوط به GetProductByCategory از طریق Postman فراخوانی می کنیم :برای این کار بصورت ذیل عمل می کنیم : https://www.aparat.com/javadjahangiriniopdc/playlists کانتینر کردن میکروسرویس با مونگودبی با استفاده از داکر کامپوز قبل شروع این مرحله می بایستی یک آشنایی مختصر با مفهوم Docker-compose داشته باشید:ابزار Docker-compose چیست؟اصطلاحا Docker Compose گرداننده و یا راهنمای کانتینر داکر است.اگر دیده باشید توی گروه های موسیقی یک رهبر ارکستر وجود داره که وظیفش  هدایت گروه تحت نظرشه و اونه که مشخص میکنه چگونه یک گروه باید در حین اجرا  رفتار کنه، صدای کم یا زیاد، ریتم و غیره.این دقیقا همون کاریه که Docker compose انجام میده، ولی توی این مورد ما  رهبر ارکستر هستیم! در حقیقت این ماییم که تعیین میکنیم کانتینر یا  کانتینرها چگونه با استفاده از یک فایل رفتار کنند. تمام داستان نوشتن یک  فایل با فرمت Yaml است (Yaml Ain’t Markup Language)در محیط Visual Studio 2019 برای ایجاد Docker-compose امکاناتی به شرح ذیل وجود دارد:بر روی گزینه  Container Orchestrator Support کلیک می کنیم و سپس  گزینه Docker Compose  را انتخاب می کنیم و  در قسمت سیستم عامل مقصد Linux  را انتخاب می کنیمابتدا اگر روی سیستم شما image مربوط به mcr.microsoft.com/dotnet/aspnet:5.0 نباشد این ایمیج بر روی سیستم شما Pull خواهد شداین عملیات زمانبر می باشد و با توجه به سرعت اینترنت تا نیم ساعت هم شاید طول بکشید بعد از این مرحله فرایندهای به شرح ذیل انجام می شود========== Pulling Images ==========
Pulling missing Docker images. To cancel this download, close the command prompt window. To disable image auto-pull, see Tools &gt; Options &gt; Container Tools.
docker pull mcr.microsoft.com/dotnet/aspnet:5.0
docker pull completed
========== Preparing Containers ==========
Getting Docker containers ready...
C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive -NoProfile -WindowStyle Hidden -ExecutionPolicy RemoteSigned -File &amp;quotC:\Users\BaharIctc\AppData\Local\Temp\GetVsDbg.ps1&amp;quot -Version vs2017u5 -RuntimeID linux-x64 -InstallPath &amp;quotC:\Users\BaharIctc\vsdbg\vs2017u5&amp;quot
Info: Using vsdbg version &#039;17.0.10712.2&#039;
Info: Using Runtime ID &#039;linux-x64&#039;
Info: Latest version of VsDbg is present. Skipping downloads
C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive -NoProfile -WindowStyle Hidden -ExecutionPolicy RemoteSigned -File &amp;quotC:\Users\BaharIctc\AppData\Local\Temp\GetVsDbg.ps1&amp;quot -Version vs2017u5 -RuntimeID linux-musl-x64 -InstallPath &amp;quotC:\Users\BaharIctc\vsdbg\vs2017u5\linux-musl-x64&amp;quot
Info: Using vsdbg version &#039;17.0.10712.2&#039;
Info: Using Runtime ID &#039;linux-musl-x64&#039;
Info: Latest version of VsDbg is present. Skipping downloads
docker-compose  -f &amp;quotD:\dev\MicroservicesUsingASP.NETCoreMongoDB\MicroservicesUsingASP.NETCoreMongoDB\docker-compose.yml&amp;quot -f &amp;quotD:\dev\MicroservicesUsingASP.NETCoreMongoDB\MicroservicesUsingASP.NETCoreMongoDB\docker-compose.override.yml&amp;quot -f &amp;quotD:\dev\MicroservicesUsingASP.NETCoreMongoDB\MicroservicesUsingASP.NETCoreMongoDB\obj\Docker\docker-compose.vs.debug.g.yml&amp;quot -p dockercompose6193082444552166584 --ansi never config
services:
  microservicesusingasp.netcoremongodb:
    build:
      context: D:\dev\MicroservicesUsingASP.NETCoreMongoDB\MicroservicesUsingASP.NETCoreMongoDB
      dockerfile: MicroservicesUsingASP.NETCoreMongoDB/Dockerfile
      labels:
        com.microsoft.created-by: visual-studio
        com.microsoft.visual-studio.project-name: MicroservicesUsingASP.NETCoreMongoDB
      target: base
    container_name: MicroservicesUsingASP.NETCoreMongoDB
    entrypoint: tail -f /dev/null
    environment:
      ASPNETCORE_ENVIRONMENT: Development
      ASPNETCORE_LOGGING__CONSOLE__DISABLECOLORS: &amp;quottrue&amp;quot
      DOTNET_USE_POLLING_FILE_WATCHER: &#039;1&#039;
      NUGET_FALLBACK_PACKAGES: /root/.nuget/fallbackpackages;/root/.nuget/fallbackpackages2
    image: microservicesusingaspnetcoremongodb:dev
    labels:
      com.microsoft.visualstudio.debuggee.arguments: &#039; --additionalProbingPath /root/.nuget/packages
        --additionalProbingPath /root/.nuget/fallbackpackages --additionalProbingPath
        /root/.nuget/fallbackpackages2  &amp;quot/app/bin/Debug/net5.0/MicroservicesUsingASP.NETCoreMongoDB.dll&amp;quot&#039;
      com.microsoft.visualstudio.debuggee.killprogram: /bin/sh -c &amp;quotif PID=$$(pidof
        dotnet); then kill $$PID; fi&amp;quot
      com.microsoft.visualstudio.debuggee.program: dotnet
      com.microsoft.visualstudio.debuggee.workingdirectory: /app
    ports:
    - target: 80
    tty: true
    volumes:
    - D:\dev\MicroservicesUsingASP.NETCoreMongoDB\MicroservicesUsingASP.NETCoreMongoDB\MicroservicesUsingASP.NETCoreMongoDB:/app:rw
    - C:\Users\BaharIctc\vsdbg\vs2017u5:/remote_debugger:rw
    - C:\Users\BaharIctc\AppData\Roaming\ASP.NET\Https:/root/.aspnet/https:ro
    - C:\Users\BaharIctc\AppData\Roaming\Microsoft\UserSecrets:/root/.microsoft/usersecrets:ro
    - C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages:/root/.nuget/fallbackpackages:ro
    - C:\Program Files (x86)\Microsoft\Xamarin\NuGet:/root/.nuget/fallbackpackages2:ro
    - C:\Users\BaharIctc\.nuget\packages:/root/.nuget/packages:ro
    - D:\dev\MicroservicesUsingASP.NETCoreMongoDB\MicroservicesUsingASP.NETCoreMongoDB:/src:rw
version: &#039;3.4&#039;
docker-compose  -f &amp;quotD:\dev\MicroservicesUsingASP.NETCoreMongoDB\MicroservicesUsingASP.NETCoreMongoDB\docker-compose.yml&amp;quot -f &amp;quotD:\dev\MicroservicesUsingASP.NETCoreMongoDB\MicroservicesUsingASP.NETCoreMongoDB\docker-compose.override.yml&amp;quot -f &amp;quotD:\dev\MicroservicesUsingASP.NETCoreMongoDB\MicroservicesUsingASP.NETCoreMongoDB\obj\Docker\docker-compose.vs.debug.g.yml&amp;quot -p dockercompose6193082444552166584 --ansi never build
Building microservicesusingasp.netcoremongodb
#1 [internal] load build definition from Dockerfile
#1 sha256:2de4178b636398d7f62590883d84d0d153cac4808b3fd9bbaea2615183367a68
#1 transferring dockerfile: 959B 0.0s done
#1 DONE 0.0s
#2 [internal] load .dockerignore
#2 sha256:96e481c075e3846ab2f2c99d08161ca833f2df785879528caa1af0b046b32f19
#2 transferring context: 382B done
#2 DONE 0.0s
#3 [internal] load metadata for mcr.microsoft.com/dotnet/aspnet:5.0
#3 sha256:3b35130338ebb888f84ec0aa58f64d182f10a676a625072200f5903996d93690
#3 DONE 0.0s
#5 [base 1/2] FROM mcr.microsoft.com/dotnet/aspnet:5.0
#5 sha256:31acc33a1535ed7869167d21032ed94a0e9b41bbf02055dc5f04524507860176
#5 DONE 0.1s
#4 [base 2/2] WORKDIR /app
#4 sha256:56abde746b4f39a24525b2b730b2dfb6d9688bcf704d367c86a4753aefff33f6
#4 DONE 0.0s
#6 exporting to image
#6 sha256:e8c613e07b0b7ff33893b694f7759a10d42e180f2b4dc349fb57dc6b71dcab00
#6 exporting layers 0.0s done
#6 writing image sha256:46d0a001d9dc736c2727e3aaee0499ec7dddebf60e631019e70f37da8b140f40 done
#6 naming to docker.io/library/microservicesusingaspnetcoremongodb:dev done
#6 DONE 0.0s
Use &#039;docker scan&#039; to run Snyk tests against images to find vulnerabilities and learn how to fix them
docker-compose  -f &amp;quotD:\dev\MicroservicesUsingASP.NETCoreMongoDB\MicroservicesUsingASP.NETCoreMongoDB\docker-compose.yml&amp;quot -f &amp;quotD:\dev\MicroservicesUsingASP.NETCoreMongoDB\MicroservicesUsingASP.NETCoreMongoDB\docker-compose.override.yml&amp;quot -f &amp;quotD:\dev\MicroservicesUsingASP.NETCoreMongoDB\MicroservicesUsingASP.NETCoreMongoDB\obj\Docker\docker-compose.vs.debug.g.yml&amp;quot -p dockercompose6193082444552166584 --ansi never up -d --no-build --force-recreate --remove-orphans
Creating network &amp;quotdockercompose6193082444552166584_default&amp;quot with the default driver
Creating MicroservicesUsingASP.NETCoreMongoDB ... 
Creating MicroservicesUsingASP.NETCoreMongoDB ... done
Done!  Docker containers are ready.ابتدا یک فایل Dockerfile با محتویات ذیل به پروژه اضافه می شود#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
WORKDIR /app
EXPOSE 80

FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src
COPY [&amp;quotMicroservicesUsingASP.NETCoreMongoDB/MicroservicesUsingASP.NETCoreMongoDB.csproj&amp;quot, &amp;quotMicroservicesUsingASP.NETCoreMongoDB/&amp;quot]
RUN dotnet restore &amp;quotMicroservicesUsingASP.NETCoreMongoDB/MicroservicesUsingASP.NETCoreMongoDB.csproj&amp;quot
COPY . .
WORKDIR &amp;quot/src/MicroservicesUsingASP.NETCoreMongoDB&amp;quot
RUN dotnet build &amp;quotMicroservicesUsingASP.NETCoreMongoDB.csproj&amp;quot -c Release -o /app/build

FROM build AS publish
RUN dotnet publish &amp;quotMicroservicesUsingASP.NETCoreMongoDB.csproj&amp;quot -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT [&amp;quotdotnet&amp;quot, &amp;quotMicroservicesUsingASP.NETCoreMongoDB.dll&amp;quot]سپس فایل های مربوط به docker-compose.yml به پروژه اضافه می شود:version: &#039;3.4&#039;
services
microservicesusingasp.netcoremongodb:
    image: ${DOCKER_REGISTRY-}microservicesusingaspnetcoremongodb
    build:
      context: .
      dockerfile: MicroservicesUsingASP.NETCoreMongoDB/Dockerfileدر نهایت پیغام Done! Docker Contianers are ready در صورتی که خطایی رخ ندهد را نمایش می دهدو در نهایت اجرای پروژه بر روی docker-compose تغییر داده می شوداضافه کردن ایمیج مونگودبی به داکر کامپوز فایل برای محیط های مولتی کانتینر داکربرای این کار وارد فایل docker-compose.yml  می شویم ابتدا یک سرویس به این فایل بنام storedb اضافه می کنیم و سپس برای اینکه درهنگام نصب و یا حذف کانتینر های اطلاعات دیتابیس حذف نشود و بعبارتی اطلاعات دیتابیس در سیستم فایل ما در یک فایل جداگانه از خود کانتینر نوشته شود یک volumes هم به فایل داکرکامپوز با نام mongo_data  اضافه می کنیمversion: &#039;3.4&#039;
services:
  storedb:
    image: mongo

  microservicesusingasp.netcoremongodb:
    image: ${DOCKER_REGISTRY-}microservicesusingaspnetcoremongodb
    build:
      context: .
      dockerfile: MicroservicesUsingASP.NETCoreMongoDB/Dockerfile

volumes:
  mongo_data:
حالا نوبت به مهم ترین فایل docker-compose.override.yml می رسد, این فایل وقتی که ما دستور می دهیم  که داکر کامپوز مجدد کانتینرها را بسازد داکر کامپوز برای رونویسی تنظیمات پروژه از این فایل استفاده می کند version: &#039;3.4&#039;

services:
  storedb:
     container_name: storedb
     restart: always
     ports:
       - &amp;quot27017:27017&amp;quot
     volumes:
       - mongo_data:/data/db

  microservicesusingasp.netcoremongodb:
    container_name: store.api
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - &amp;quotDatabaseSettings:ConnectionString=mongodb://storedb:27017&amp;quot
    depends_on:
      - storedb
    ports:
      - &amp;quot8080:80&amp;quotبرای سرویس storedb که همانگونه که مستحضرید هر سرویس به یک داکر کانتینر در نهایت تبدیل می شود ابتدا برای کانتینر یک اسم می دهیم و سپس بهش اعلام می کنیم که اگر در حین استارت کانتینر به مشکل برخورد کرد همیشه کانتینر ریست شود و پورت 27017 برای کانتینر تنظیم کرده و والیومی که دیتاهای مونگودبی باید در ان مسیر نوشته شود را  /data/db/ را برای ان تنظیم می کنیم سپس برای کانتینر اصلی پروژه یک نام بنام store.api می دهیم و سپس در پیشنیازهای این سرویس اعلام می کنیم که قبل از استارت این کانتینر باید کانتینر storedb باید ابتدا استارت شده باشد و مشخص می کنیم که پورت ان نیز از 8000 به 80 منتقل شود توجه شود چون ما در این مقاله برای مونگودبی یک کانتینر ایجاد کرده بودیم و روی پورت 27017 در حال سرویس می باشد فراموش نشود که این کانتینر را ابتدا stop کرده و سپس ان را پاک کنید چون در غیراینصورت با پیغام خطا ذیل روبه رو می شوید:A non-critical error occurred while getting containers ready.  Your project will continue to function normally.  The error was: ERROR: for storedb  Cannot start service storedb: driver failed programming external connectivity on endpoint storedb (8b42b5ae481272cbad790749fbdff47609ec1552047a893817d5e5987bb9d064): Bind for 0.0.0.0:27017 failed: port is already allocatedIf the error persists, try restarting Docker Desktop.در نهایت برای اجرای پروژه بر روی گزینه docker-composer کلیک می کنیم ابتدا پروژه یکبار build شده و سپس در پشت پرده  کانتینر ساخته شده و استارت می شودنکته :توجه شود که هنگامی که ما docker-composer را با استفاده از ابزار Container Orchestrator Support می سازیم در هنگام هر تغییرات در فایل های docker-compose.yml و یا docker-compose.override.yml بصورت اتوماتیک دستور فوق در پشت پرده بصورت اتوماتیک اجرا می شودنکته : چون ما دیتابیس پروژه رو بر روی داکر جدید انتقال دادیم که داخل کانتینر با نام storedb می باشد فراموش نشود که رشته اتصال در فایل appsetting.json پروژه به شرح زیر تغییر داده شودو در نهایت این هم از نتیجه اجرای پروژه ای که بر روی داکر پابلیش شده است https://www.aparat.com/javadjahangiriniopdc اگر بخواهید پروژه را بصورت مستقیم بدون محیط ویژال استادیو اجرا کنیم کافی وارد پوشه پروژه شده و دستور زیر را اجرا کنیدdocker-compose -f docker-compose.yml -f docker-compose.override.yml up -d https://www.aparat.com/javadjahangiriniopdc/playlists باتشکر از مطالعه مقاله ,مثل همیشه کنجکاو باشید !!!در دوره های آموزش تضمینی مجتمع فنی ارومیه که به صورت خصوصی و عمومی در دو شیوه حضوری و آنلاین برگزار می شود سرفصل های بسیار متنوع و کاربردی را بصورت پروژه محور آموزش داده می شود تا شخص کارآموز بتواند بلافاصله پس از اتمام این دوره در کمترین زمان ممکن وارد بازار کار شود.آموزش تخصص ماست با ما حرفه ای شویدجهت مشاوره با شماره 09149431772 در ارتباط باشید ...</description>
                <category>جواد جهانگیری</category>
                <author>جواد جهانگیری</author>
                <pubDate>Fri, 22 Oct 2021 18:09:20 +0330</pubDate>
            </item>
                    <item>
                <title>آموزش MongoDBCompass در مونگودبی</title>
                <link>https://virgool.io/@javadjahangiri/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-mongodbcompass-%D8%AF%D8%B1-%D9%85%D9%88%D9%86%DA%AF%D9%88%D8%AF%D8%A8%DB%8C-ffdeooxnhrpy</link>
                <description>آموزش MongoDBCompass در مونگودبیبه نام آن که جان را فکرت آموخت / چراغ دل به نور جان برافروختدر این مقاله از سری مقاله های آموزشی مونگودبی به آموزش قطب نما (MongoDBCompass) بصورت کاربردی و پروژه محور پرداخته می شود.MongoDBCompass یک ابزار رابط گرافیکی برای مدیریت پایگاه ها داده های مونگودبی می باشد . از طریق این ابزار می توان اکثر عملیات در مونگودبی همانند عملیات Curd , پشتیبان گیری و Import/Export داده ها بصورت گرافیکی بدون نوشتن دستی درخواست ها انجام داد.ایده این سری مقاله های آموزشی از این موضوع سرچشمه می گیرد که بخشی از خوانندگان وجود دارد که به محتوای نوشتاری آنلاین بهتر پاسخ می دهند و ترجیج می دهند مهارت های جدید را به سرعت از طریق خواندن افزایش دهند.این سری اموزش ها با ارایه اولین پکیج آموزشی در خصوص مانگودبی آغاز می شود که انتظار می رود با واکنش مثبت کاربران همراه شود.توجه: این مقاله به مرور زمان، ویرایش و یا تکمیل می‌شود!تقاضا: در صورتی که با مشکل تایپی، دستوری و یا مفهومی در این مقاله برخورد کردید، از شما دوست عزیز و گرامی، صمیمانه تقاضا می‌کنم که اینجانب را مطلع کرده، تا نسبت به تصحیح و یا تکمیل آن، در اسرع وقت، اقدام نمایم. با کمال تشکر جواد جهانگیریشماره تلفن همراه: 09149431772نشانی پست الکترونیکی: javad.jahangiri.niopdc@gmail.comفیلم‌های آموزشی در آپارات:جواد جهانگیری (CTO) - آپاراتفیلم آموزشی در یوتویب: javad jahangiri - YouTubeنسخه مقاله: ۱.۱ - تاریخ بروزرسانی: 1400/09/09قطب نمای مونگودبی (MongoDBCompas) چیست؟MongoDB Compass یک GUI قدرتمند برای پرس و جو ، تجمیع و تجزیه و تحلیل داده های MongoDB شما در یک محیط بصری است. استفاده از قطب نما رایگان است و منبع آن در دسترس است و می تواند در macOS ، Windows و Linux اجرا شودچه کارهای با MongoDBCompas می تواند انجام داد؟Visually Explore Your Dataبرخی از وظایفی را که قطب نما می تواند به شما در انجام آنها کمک کند ، مانند وارد کردن و مدیریت داده ها از طریق رابط کاربری آسان ، کاوش کنید.Connect to your deploymentبه استقرار MongoDB که در اطلس MongoDB میزبانی شده است ، یا استقرار محلی در دستگاه خود متصل شوید.Import your dataداده ها را از فایل های CSV یا JSON به پایگاه داده MongoDB خود وارد کنید.Insert documents into your collectionsاسناد را در نمای JSON بچسبانید ، یا اسناد را با استفاده از ویرایشگر فیلد به میدان وارد کنید.اسناد را به دو روش در JSON Mode و یک ویرایشگر Field-by-Field در مجموعه خود وارد کنید.Query your dataبرای فیلتر کردن داده های خود ، درخواستهای موقت بنویسید. روندها و اشتراکات موجود در مجموعه های خود را کاوش کنید.Create aggregation pipelinesخطوط تجمیعی بنویسید که به اسناد یک مجموعه یا نمای اجازه می دهد از چندین مرحله عبور کنند و در آنجا به مجموعه ای از نتایج تجزیه و تحلیل شوند.Work with your data in the MongoDB Shellبرای کنترل داده های خود در یک محیط جاوا اسکریپت تعاملی ، از MongoDB Shell در Compass استفاده کنیدنحوه نصب و راه اندازی قطب نمای مونگودبی (MongoDBCompas)کاربران محترم سایت ویرگول نحوه نصب و راه اندازی MongoDBCompas بهمراه خود مونگودبی در مقاله آموزشی آموزش دیتابیس مونگودبی MongoDB Tutorial ارایه شده است که پیشنهاد می شود قبل از مطالعه این مقاله ,ابتدا مقاله مذکور مطالعه و MongoDBCompas نصب شود.MongoDB AtlasMongoDB Atlas یک پایگاه داده ابری کاملاً مدیریت شده است که توسط همان افرادی که MongoDB را ایجاد می کنند توسعه یافته است. اطلس تمام پیچیدگی استقرار ، مدیریت و بهبود استقرارهای شما را در ارائه دهنده خدمات ابری به دلخواه (AWS ، Azure و GCP) مدیریت می کند.نحوه اتصال به مونگودبی از طریق MongoDBCompasاستارت سرویس مانگودبیکاربران ویندوزی قبل از اتصال به مونگودبی توسط MongoDBCompas می بایستی از طریق سرویس ویندوز می بایستی سرویس مانگودبی را استارت نمایند زیرا این سرویس بصورت پیش فرض غیرفعال می باشداز طریق گزینه start سرویس را فعال می کنیممی توانید از طریق گزینه کانکت به سرویس local مونگودبی وصل شد و یا به سرویس ابری اطلس مونگودبی اتصال پیدا کرد در این اموزش ما به سرویس محلی مونگودبی که روی سیستم عامل خودمان نصب است متصل می شویم در زیر یک نمونه کانکشن استرینگ برای اتصال قرارداده شده است.
mongodb://localhost:27017/?readPreference=primary&amp;appname=MongoDB%20Compass&amp;directConnection=true&amp;ssl=falseبعد از وصل شدن به سرور محلی مونگودبی لیست دیتابیس های قابل دسترس به ما نمایش داده می شود.نحوه ایجاد دیتابیس مونگودبی توسط MongoDBCompasبرای ایجاد دیتایس توسط قطب نمای مونگودبی بر روی گزینه سبز رنگ create database از منو بالا کلیک کنیدسپس نام دیتابیس و اولین کالکشن مورد نظر را وارد می کنیمسپس از طریق مرورگر دیتابیس ,می توان مشاهده کرد که دیتابیس جدید با اولین کالکشن به مونگودبی اضافه گردیدنحوه مشاهده اطلاعات Host مونگودبی در MongoDBCompasبرای مشاهده اطلاعات مربوط به هاست مونگودبی و اطلاعات کلاستر مونگودبی و نسخه سرور نصب شده بر روی ماشین محلی خود می تواند بر روی گزینه local از اسلایدبار سمت چپ می شود این کار را براحتی انجام دادنحوه مشاهده پرفورمانس مونگودبی توسط MongoDBCompasبرای مشاهده پرفورمانس مونگودبی و مانیتورکردن وضعیت سرور مانگودبی کافی است از تب های بالا بر روی گزینه performance کلیک می کنیدکه اطلاعاتی در میزان خواندن و نوشتن سرور،وضعیت شبکه و حافظه سرور و ... را به ما نمایش می دهدپرفورمانس سرور مونگودبینحوه نمایش کالکشن ها و داکیومنت های موجود در یک دیتابیس مونگودبی در MongoDBCompasبرای مشاهده اطلاعات کالکشن های یک دیتابیس و تعداد داکیومنت های موجود در هر کالکشن و میانگین سایر داکیومنت های کالکشن ، کل سایز داکیومنت ها و تعداد ایندکس کافی است بر روی اسم دیتابیس مورد نظر در صفحه اصلی کلیک کنید:نحوه مرور داکیومنت های موجود در یک کالکشن ، یک دیتابیس مونگودبی توسط MongoDBCompasبرای این کار کافی است بر روی نام کالکشن مورد نظر کلیک کنیم و داکیومنت های موجود در کالکشن نمایش داده می شودبا کلیک داکیومنت مطابق شکل زیر نمایش داده می شود:نحوه نمایش اطلاعات داکیومنت های موجود در یک کالکشن مونگودبی بصورت json در MongoDBCompasبرای این کار بر روی گزینه {} مطابق شکل زیر کلیک می کنیم تا نمایی json از اطلاعات bjson داکیومنت های (رکوردهای ) یک کالکشن (جدول) را داشته باشیدنحوه نمایش جدولی  داکیومنت های (رکوردها) موجود در یک کالکشن (جدول ) دیتابیس مونگودبی توسط ابزارMongoDBCompasبرای این کار بر روی گزینه نمایش جدولی مطابق شکل زیر کلیک می کنیدتا اطلاعات بصورت جدولی در سطر و ستون بصورت خلاصه نمایش داده شود:نحوه ویرایش اطلاعات داکیومنت ها (رکوردها) موجود در یک کالکشن (جدول ) دیتابیس مونگودبی توسط ابزار MongoDBCompasبرای این کار بر روی اطلاعات نمایش داده کلیک می کنید اطلاعات را ویرایش و در نهایت بری روی گزینه update کلیک می گردد:نحوه درج اطلاعات توسط ابزار MongoDBCompas در مونگودبیبرای درج اطلاعات بر روی گزینه ADD DATA کلیک می کنید و سپس بر روی گزینه Insert Document کلیک نمایید:سپس با استفاده از فرمت json داکیومنت جدید (رکوردجدید ) را وارد کرده و سپس گزینه insert را کلیک می نمایید:و رکورد جدید بصورت زیر اضافه شده و یک شناسه _id به ان اختصاص داده می شودنکته:توجه شود می توانید در هنگام درج کردن اطلاعات از طریق ابزارهای MongoDBCompas می توانید براحتی بدون فرمت json نیز مطابق شکل زیر اطلاعات را وارد کنید:برای مثال بر روی گزینه Add Field After کلیک می کنید و به ترتیب اطلاعات فیلدهای مورد نظر در یک کادر محاوره ای بصورت ریکتیو وارد می کنیدنحوه export کردن اطلاعات یک کالکشن (جدول ) در مونگودبی توسط ابزار MongoDBCompas برای این کار بر روی گزینه Export Collection مطابق شکل زیر کلیک می نمایید:سپس یا از طریق دستورات مونگودبی که در مقاله (آموزش مونگودبی) اموزش داده شده است اطلاعات را فیلتر می کنید و یا کل کالکشن را انتخاب می کنید:سپس در مرحله بعدی فیلدهای موردنظر خود برای اکسپورت اطلاعات را انتخاب می کنید:و در مرحله اخر فرمت اکسپورت داده ها که می تواند Json و یا Csv باشد را انتخاب می کنیم و یک نام به فایل مورد نظر میدهید و بر روی گزینه export کلیک می گردد:فایل خروجی برای ما ایجاد می شود نحوه import کردن اطلاعات در مونگودبی توسط ابزار MongoDBCompas برای ایمورت کردن داده ها ابتدا بر روی گزینه ADD DATA کلیک می کنید و سپس بر روی گزینه Import File کلیک می نمایید:سپس فایل و فرمت فایل مورد نظر برای ایمپورت اطلاعات را انتخاب می گردد و سپس بر روی گزینه import کلیک می کنید که عملیات ایمپورت اطلاعات شروع شود. https://www.aparat.com/javadjahangiriniopdc/playlists نحوه نوشتن پرس و جو (ًQuery) در مونگودبی توسط ابزار MongoDBCompasیک دیتابیس بنام بلاگ(blog) با یک کالکشن (جدول) post ایجاد کنید:برای درج اطلاعات از گزینه ADD DATA و گزینه Insert Document استفاده می شود:[
	{
                &amp;quot_id&amp;quot: {&amp;quot$oid&amp;quot: &amp;quot616ff6717ee16fa4c6b59ee2&amp;quot },
		&amp;quottitle&amp;quot: &amp;quotMongoDB Overview&amp;quot,
		&amp;quotdescription&amp;quot: &amp;quotMongoDB is no SQL database&amp;quot,
		&amp;quotby&amp;quot: &amp;quottutorials point&amp;quot,
		&amp;quoturl&amp;quot: &amp;quothttp://www.tutorialspoint.com&amp;quot,
		&amp;quottags&amp;quot: [&amp;quotmongodb&amp;quot, &amp;quotdatabase&amp;quot, &amp;quotNoSQL&amp;quot],
		&amp;quotlikes&amp;quot: 100
	},
	{
        &amp;quot_id&amp;quot: {&amp;quot$oid&amp;quot: &amp;quot616ff6717ee16fa4c6b59ee3&amp;quot},
	&amp;quottitle&amp;quot: &amp;quotNoSQL Database&amp;quot,
	&amp;quotdescription&amp;quot: &amp;quotNoSQL database doesn&#039;t have tables&amp;quot,
	&amp;quotby&amp;quot: &amp;quottutorials point&amp;quot,
	&amp;quoturl&amp;quot: &amp;quothttp://www.tutorialspoint.com&amp;quot,
	&amp;quottags&amp;quot: [&amp;quotmongodb&amp;quot, &amp;quotdatabase&amp;quot, &amp;quotNoSQL&amp;quot],
	&amp;quotlikes&amp;quot: 20,
	&amp;quotcomments&amp;quot: [
		{
			&amp;quotuser&amp;quot:&amp;quotuser1&amp;quot,
			&amp;quotmessage&amp;quot: &amp;quotMy first comment&amp;quot,
			&amp;quotdateCreated&amp;quot: &amp;quot2013-12-09T23:05:00Z&amp;quot,
			&amp;quotlike&amp;quot: 0
		}
	]
}
]مطابق شکل زیر کد درج در این قسمت کپی می کنید و گزینه INSERT را کلیک نمایید:نکته دقت شود در هنگام درج اطلاعات در ابزار MongoDBCompas می بایستی نام فیلدها بین دابل کوتیشن باشد و همچنین تاریخ هم بصورت تاریخ پیوسته وارد شد.مثال اول : اطلاعات رکوردی را که عنوان برابر با MongoDB Overview می باشد را فیلتر کنید:مثال دوم: رکوردهای که تعداد like های بیشتر یا مساوی 20 مورد باشد را جستجو کنید:برای حل این مثال ابتدا بایستی به جدول اپراتورهای مقایسه ای  زیر دقت شود برای بیشتر یا مساوی می بایستی از اپراتور gte$ استفاده شود:اپراتورهای مقایسه ای در مونگودبیسپس به شکل ذیل کد مربوطه در قسمت find وارد کنید و بر گزینه find کلیک نمایید:{likes:{$gte:20}}مثال سوم:پرس جوی در مونگودبی بنویسید که رکوردهای که عنوان ان شامل &quot;NoSQL Database&quot;,&quot;MongoDB Overview&quot; باشد را نمایش دهد{title:{$in:[&amp;quotNoSQL Database&amp;quot,&amp;quotMongoDB Overview&amp;quot]}}مثال چهارم:پرس جوی در مونگودبی بنویسید که رکوردهای که عنوان ان MongoDB Overview و تعداد like ان از 20 بیشتر باشد را نمایش دهد:برای نوشتن این پرس و جوی می بایستی به اپراتورهای منطقی زیر توجه شود:اپراتورهای منطقی در مونگودبی{$and:[{title:&amp;quotMongoDB Overview&amp;quot},{likes:{$gte:20}}]}نکته در مورد and کردن در مونگودبی می توانید از طریق جداکننده کاما (,)  بین اپراتورها نیز استفاده کرد{title:&quot;MongoDB Overview&quot;,likes:{$gte:20}}مثال پنجم: پرس و جوی را در مونگودبی بنویسید که رکوردهای که دارای کامنت باشد را به ما نمایش دهد:شکل کلی استفاده از اپراتور exists$ به شرح ذیل می باشد:{ field: { $exists: &lt;boolean&gt; } }پاسخ:{comments:{$exists:true}} مثال ششم:پرس و جوی در مونگودبی بنویسید که فیلدهای عنوان (title ) و توضیحات (description) برای رکوردهای بیشتر از 20 تا like  را نمایش دهد:نکته:فیلد _id نمایش داده می شود اگر می خواهید نمایش داده شود کافی است id:0 قرار دهیدمثال هفتم:پرس و جوی بنویسید که اطلاعات مثال ششم بصورت صعودی براساس title بصورت صعودی نمایش دهد:مثال هشتم : پرس و جوی را بنویسید که تمامی رکوردهای که فیلد tags آن برابر سه مقدار &quot;mongodb&quot;, &quot;database&quot;,&quot;NoSQL&quot; باشد را نمایش دهد:دقت شود برای زدن پرس و جو بر روی مقادیر آرایه (Array) از علامت  براکت باز و بسته [ ] استفاده می شود فقط در این حالت رکورد ها که دقیقا tags شامل سه مورد یاد شده نمایش داده می شود:{ tags: [&amp;quotmongodb&amp;quot, &amp;quotdatabase&amp;quot,&amp;quotNoSQL&amp;quot] } اگر گفته شود فقط یک مقدار آرایه ای شامل یک مقدار باشد در این صورت نیازی به استفاده از براکت نمی باشد:{ tags:&amp;quotmongodb&amp;quot} نکته:اگر گفته شود که یک مقدار آرایه ای شامل  موردهای &quot;mongodb&quot; و &quot;database&quot; باشد در اینصورت می بایستی از اپراتور all$ بهمراه براکت استفاده می شود:{ tags:{$all:[&amp;quotmongodb&amp;quot,&amp;quotdatabase&amp;quot]}} مثال نهم: پرس و جوی در مونگودبی بنویسید که رکوردهای که تعداد tagsهای برابر 3 می باشد را نمایش دهد.همانطور که در مثال یاد شده آمده است tags از نوع آرایه می باشد و برای فیلتر کردن سایز آرایه می توانید از size$ استفاده می شود{ tags:{$size:3}} آموزش aggregation pipeline در مونگو دی بیابتدا وارد دیتابیس blog شوید و کالکشن post را که در مثال های قبلی ایجاد کرده بودید را پاک کنیدحالا از طریق کد زیر در حدود 1000 رکورد تصادفی در داخل کالکشن post ایجاد می کنید:use blogby=[&#039;tutorials point&#039;,&#039;w3schools&#039;,&#039;tutorialsteacher&#039;,&#039;udemy&#039;]
url=[&#039;http://www.tutorialspoint.com&#039;,&#039;http://www.w3schools.com&#039;,&#039;https://www.tutorialsteacher.com/&#039;,&#039;https://www.udemy.com&#039;]
for(i=0;i&lt;1000;i++){
       j=Math.round(Math.random()*3);
       db.post.insert({
            &#039;_id&#039;:i,
           &#039;title&#039;:&#039;title_&#039;+Math.round(Math.random()*3),
            &#039;description&#039;:&#039;description_&#039;+Math.round(Math.random()*3),
           &#039;by&#039;:by[j],
           &#039;url&#039;:url[j],
           &#039;likes&#039;:Math.round(Math.random()*3),
   });
}تعداد 1000 رکورد با اطلاعات تصادفی در کالکشن post درج می شود:مثال دهم:پرس و جو بنویسید که رکوردهای که عنوان انها &#x27;title_0&#x27; باشد بر اساس فیلد by دسته بندی نمایید به نحوه که مشخص شود مجموع likes هر دسته چه تعداد می باشد:عملیات های خلاصه سازی در تمامی دیتابیس های مهم می باشد برای مثال دستور groupby بهمراه having در دتیابیس های رابطه ای جز مهم ترین موضوعات می باشد و توابع Aggregation در SQL برای برگشت یک مقدار که از دسته بندی (گروه بندی) مقادیر مختلف دخیره شده در یک ستون ,استفاده می نمایید.MongoDB از سه راه برای انجام Aggregration استفاده می کند: aggregation pipeline ، map-reduce function و متدهای single purpose aggregationدر این مثال تمرکز ما بر روش aggregation pipeline می باشد و سعی می کنیم با مثال های مختلف که ارایه می شود  تسلط کافی برای دوستان در این راستا ایجاد شود Aggregration مربوط به MongoDB بر اساس مفهوم data processing pipeline طراحی شده است. Aggregation pipeline مشابه UNIX world pipeline است. در مراحل اولیه یک collection داریم . این collection از طریق اسناد (document) ارسال می شود. این اسناد در طول خط لوله ها انتقال پیدا می کنند و در قالب stage  هایی قرار می گیرند تا در نهایت، ما بتوانیم از آن ها یک نتیجه واحد بگیریمهمانطور که در شکل بالا می بینید که collection از stage های مختلفی عبور می کند که برخی از آن ها عبارتند از: $project, $match, $group, $sort. هر کدام از این stage ها می توانند چندین بار تکرار شوند.stage های مختلف در pipeline (خط لوله) عبارتند از:$project ، داده ها را انتخاب و فرم دهی می کند.$match ، داده ها را فیلتر می کند.$group داده ها را aggregrate می کند.$sort داده ها را مرتب می کند.$skipداده ها را skip می کند.$limit داده ها را محدود می کند.$unwind داده ها را نرمال سازی می کند.ابتدا بر روی گزینه Aggregation از tab های بالای کلیک می کنیم به ترتیب ابتدا می بایستی یک استیج از نوع $match به پروژه اضافه کنیم و در ان براساس مثال title_0 فیلتر کنیم سپس یه استیج از نوع group$ به pipeline اضافه می کنیم که گروه بندی بر اساس فیلد by باشد و مجموع تعداد likes ها برای ما نمایش دهدنکته: فیلدها در استیج ها با پیشوند $ مقدار دهی می شوند تا به این وسیله mongo shell درک کند که این فیلد جز فیلدهای اصلی سند می باشدمثال یازدهم: پرس و جوی مثال دهم را به نحوه تغییر دهید که عنواین با حروف بزرگ بررسی شود:برای حل این مثال می بایستی قبل از استیج match$ از طریق استیج project$ فیلد عنوان را به حروف بزرگ تبدیل کنیم :در فاز $project، ما می توانیم یک کلید اضافه کنیم، یک کلید حذف کنیم، یک کلید را باز سازی کنیم. همچنین توابع ساده ای نیز وجود دارند که ما می توانیم بر روی کلیدهایمان پیاده سازی کنیم:$toUpper, $toLower, $add, $multiply  و غیره...وارد tab مربوط به aggregation بشوید و از استیج project$ را انتخاب کنید و سپس برای این پروجکشن را اعمال کنیم فیلدهای که می خواهید انتخاب کنید چون به فیلد id نیازی نداریم ان را 0 می کینم برای title از طریق تابع $toUpper عنواین را به حروف بزرگ تبدیل می کنید,سپس با عنایت به اینکه در مرحله بعدی برای گروه بندی به فیلد by و برای محاسبه مجموع likes به فیلد لایک ها نیاز داریم این دوتا فیلد را نیز از طریق یک کرد مقدار انتخاب نمایید.سپس بقیه مراحل دقیقا مثل مثال دهم می باشد فقط در استیج match$ چون عنواین به حروف بزرگ تبدیل شده است باید TITLE_0 با حروف بزرگ را وارد گردد:حال فرض شود از ما خواسته می شود که نتیجه پرس و جو براساس فیلد By که دسته بندی براساس آن انجام شده است بصورت صعودی نمایش داده شوداگر درخواست نتایج پرس و جو بصورت مرتب نزولی براساس فیلد مجموع لایک ها نمایش داده شود در اینصورت می بایستی براساس sumlikes مرتب شوددر نهایت فرض کنید درخواست شده که در نتیجه نهایی رکورد اول skip شود و نتیجه نهایی به دو رکورد محدود شود برای این کار مطابق شکل زیر عمل می شود:نحوه lookup در mongodb برای join زدن بین collectionهاهمونطور که مستحضرید دیتابیس  MongoDB یک پایگاه‌داده رابطه‌ای   مثل  SQL نیست اما شما میتونین با استفاده از استیج lookup$،بین collectionها left outer join انجام بدین و پرس و جوهای مورد نظرتون رو ایجاد نمایید.شکل دستوری استفاده از استیج lookup$ بصورت ذیل می باشد:{
   $lookup:
     {
       from: &lt;collection to join&gt;,
       localField: &lt;field from the input documents&gt;,
       foreignField: &lt;field from the documents of the &amp;quotfrom&amp;quot collection&gt;,
       as: &lt;output array field&gt;
     }
}from : نام اون collection در database فعلی که قصد داریم با اون join بزنیم رو در اینجا مشخص میکنیم.localField : نام فیلد در collection فعلیforeignField : نام فیلد در collection مقصد. عملگر lookup در mongodb این دو فیلد localField و foreignField رو با هم بررسی میکنه و document هایی که برابر هستند رو انتخاب میکنه و در اختیار ما قرار میده.as : با استفاده از این مورد نام فیلد جدیدی که به collection فعلی اضافه میشه و آرایه‌ای از نتایج در اون قرار میگیره رو مشخص میکنیم.اگر قصد داشتیم در SQL همچنین کاری رو انجام بدیم، بصورت زیر عمل میکردیم: SELECT *, &lt;output array field&gt;
FROM collection
WHERE &lt;output array field&gt; IN (SELECT *
                               FROM &lt;collection to join&gt;
                               WHERE &lt;foreignField&gt;= &lt;collection.localField&gt;);برای درک این موضوع یک دیتابیس جدید به نام store ایجاد می کنیم که دارای دو کالکشن بنام orderapp و inventory باشد و یکسری رکورد به شرح ذیل در آن درج می کنید:برای کالکشن OrderApp از سندهای ذیل برای درج استفاده کنید:
[{
  &amp;quot_id&amp;quot: {
    &amp;quot$oid&amp;quot: &amp;quot6172597c1b0c3f4c18445746&amp;quot
  },
  &amp;quotcustomer&amp;quot: {
    &amp;quot_id&amp;quot: &amp;quot2&amp;quot,
    &amp;quotname&amp;quot: &amp;quotamin&amp;quot,
    &amp;quotfamily&amp;quot: &amp;quotjahangiri&amp;quot
  },
  &amp;quotproducts&amp;quot: [
    {
      &amp;quotname&amp;quot: &amp;quotpen&amp;quot,
      &amp;quotprice&amp;quot: &amp;quot100&amp;quot,
      &amp;quotquantity&amp;quot: &amp;quot2&amp;quot,
      &amp;quotpriceall&amp;quot: &amp;quot200&amp;quot,
      &amp;quotDateAt&amp;quot: {
        &amp;quot$date&amp;quot: &amp;quot2021-10-21T20:30:00Z&amp;quot
      }
    },
    {
      &amp;quotname&amp;quot: &amp;quotbook&amp;quot,
      &amp;quotprice&amp;quot: &amp;quot200&amp;quot,
      &amp;quotquantity&amp;quot: &amp;quot2&amp;quot,
      &amp;quotpriceall&amp;quot: &amp;quot400&amp;quot,
      &amp;quotDateAt&amp;quot: {
        &amp;quot$date&amp;quot: &amp;quot2021-09-21T20:30:00Z&amp;quot
      }
    },
    {
      &amp;quotname&amp;quot: &amp;quottable&amp;quot,
      &amp;quotprice&amp;quot: &amp;quot200&amp;quot,
      &amp;quotquantity&amp;quot: &amp;quot2&amp;quot,
      &amp;quotpriceall&amp;quot: &amp;quot400&amp;quot,
      &amp;quotDateAt&amp;quot: {
        &amp;quot$date&amp;quot: &amp;quot2021-09-21T20:30:00Z&amp;quot
      }
    }
  ]
},{
  &amp;quot_id&amp;quot: {
    &amp;quot$oid&amp;quot: &amp;quot6172597c1b0c3f4c18445745&amp;quot
  },
  &amp;quotcustomer&amp;quot: {
    &amp;quot_id&amp;quot: &amp;quot1&amp;quot,
    &amp;quotname&amp;quot: &amp;quotjavad&amp;quot,
    &amp;quotfamily&amp;quot: &amp;quotjahangiri&amp;quot
  },
  &amp;quotproducts&amp;quot: [
    {
      &amp;quotname&amp;quot: &amp;quotpen&amp;quot,
      &amp;quotprice&amp;quot: &amp;quot100&amp;quot,
      &amp;quotquantity&amp;quot: &amp;quot2&amp;quot,
      &amp;quotpriceall&amp;quot: &amp;quot200&amp;quot,
      &amp;quotDateAt&amp;quot: {
        &amp;quot$date&amp;quot: &amp;quot2021-10-21T20:30:00Z&amp;quot
      }
    },
    {
      &amp;quotname&amp;quot: &amp;quottable&amp;quot,
      &amp;quotprice&amp;quot: &amp;quot300&amp;quot,
      &amp;quotquantity&amp;quot: &amp;quot2&amp;quot,
      &amp;quotpriceall&amp;quot: &amp;quot600&amp;quot,
      &amp;quotDateAt&amp;quot: {
        &amp;quot$date&amp;quot: &amp;quot2021-09-21T20:30:00Z&amp;quot
      }
    }
  ]
}]برای درج سند در کالکشن inventory نیز از اطلاعات ذیل استفاده کنید:[{
  &amp;quot_id&amp;quot: {
    &amp;quot$oid&amp;quot: &amp;quot617270bbfded3202514607b6&amp;quot
  },
  &amp;quotproduct&amp;quot: &amp;quotbook&amp;quot,
  &amp;quotdescription&amp;quot: &amp;quotbook products&amp;quot,
  &amp;quotquantity&amp;quot: 30
},{
  &amp;quot_id&amp;quot: {
    &amp;quot$oid&amp;quot: &amp;quot617270bbfded3202514607b7&amp;quot
  },
  &amp;quotproduct&amp;quot: &amp;quotpen&amp;quot,
  &amp;quotdescription&amp;quot: &amp;quotpen products&amp;quot,
  &amp;quotquantity&amp;quot: 20
},{
  &amp;quot_id&amp;quot: {
    &amp;quot$oid&amp;quot: &amp;quot617270bbfded3202514607b8&amp;quot
  },
  &amp;quotproduct&amp;quot: &amp;quottable&amp;quot,
  &amp;quotdescription&amp;quot: &amp;quottable products&amp;quot,
  &amp;quotquantity&amp;quot: 10
}]حال ما یک کالکشن سفارشات (جدول سفارشات ) داریم که حاوی اطلاعات مشتری که خرید را انجام داده بهمراه اطلاعات محصولات خریداری شده به ریز را شامل می شود و یک کالکشن فهرست اموال داریم که شامل تعداد موجودی این کالا در انبار می باشد حال می خواهیم بین این دو کالکشن یک join ایجاد کنیم:برای این کار ابتدا به کالکشن OrderApp بروید و بعنوان کالکشن مبدا انتخاب شود سپس به قسمت Aggregations بروید و یک استیج از نوع lookup$ را انتخاب کیندسپس مطابق کد زیر کالکشن مقصد روی inventory و فیلد محلی را از کالکشن مبدا که در این مثال سفارشات می باشد را بر روی products.name و فیلد خارجی از کالکشن مقصد را برروی product قرار میدهیم و برای فیلد جدید inventory_product را نام گذاری می کنید {
 from: &#039;inventory&#039;,
 localField: &#039;products.name&#039;,
  foreignField: &#039;product&#039;,
  as: &#039;inventory_product&#039;
}نکته: دقت شود در این مثال کالکشن سفارشات شامل یک فیلد بعنوان Products می باشد که ارایه از کالاهای خریداری شده که شامل نام ،مبلغ ، تعداد ، قیمت ,قیمت کل و تاریخ سفارش را شامل می باشد لذا برای دسترسی بعنوان محصولات می بایستی بصورت products.name  در استیج lookup$ انتخاب شوداستفاده از شروط پیچیده در lookupاز نسخه 3.6 به بعد pipeline اضافه شده است که میتونین با استفاده از اون پیشرفته‌تر از lookup استفاده کنید. شما میتونین با استفاده از یک syntax دیگه از شروط پیچیده‌تری در lookup‌ها استفاده کنید و نتایج دقیق‌تری رو بدست بیارید. Syntax این مورد بصورت زیر هست:{
   $lookup:
     {
       from: &lt;collection to join&gt;,
       let: { &lt;var_1&gt;: &lt;expression&gt;, …, &lt;var_n&gt;: &lt;expression&gt; },
       pipeline: [ &lt;pipeline to execute on the collection to join&gt; ],
       as: &lt;output array field&gt;
     }
}ویژگی‌های from و as مانند قبل هستند. ویژگی‌های دیگر بصورت زیر تعریف میشن:ویژگی let: چون در pipeline به فیلدهای کالکشن مقصد دسترسی نداریم لذا برای ایجاد join که از طریق دستور $and در pipeline ایجاد می شود برای دسترسی به متغییرهای کالکشن مقصد ابتدا باید در قسمت let تعریف شود ,به متغییر های کالکشن مبدا در pipeline دسترسی داریدویژگی pipeline: با استفاده این ویژگی می توانید بین کالکشن ها join ایجاد کرده و فیلترهای مقتضی را اعمال و فیلدهای مورد نظر خود را انتخاب کنید.اگر بخواهیم در SQL همچنین query رو بزنیم، بصورت زیر عمل میکنیم:SELECT *, &lt;output array field&gt;
FROM collection
WHERE &lt;output array field&gt; IN (SELECT &lt;documents as determined from the pipeline&gt;
                               FROM &lt;collection to join&gt;
                               WHERE &lt;pipeline&gt; );حالا می خواهیم مثال قبل را با استفاده از امکانات جدید مونگودبی باز نویسی کنیم و بین کالکشن سفارشات و کالکشن لیست اموال یک رابطه ایجاد کنید براساس Syntax جدید فقط به ویژگی های from,as,let,pipeline نیاز دارید:کالکشن (جدول) سفارشات را بعنوان کالکشن مبدا انتخاب می کنید و به قسمت Aggregation رفته و یک استیج از نوع lookup$ را انتخاب می کنید.کالکشن (جدول) مقصد را از طریق فیلد from بر روی inventory  می گذاریددر قسمت let چون در قسمت pipeline به فیلدهای کالکشن مقصد (inventory) دسترسی ندارید یک فیلد بنام products_inventory تعریف می نمایید و مقدار آن برابر فیلد product از کالکشن مقصد (inventory  ) مقدار دهی می کنید ما برای ایجاد join بین کالکشن مبدا براساس products.name و در کالکشن مقصد براساس فیلد product به این متغییر نیاز خواهید داشت.در قسمت pipeline ابتدا یک استیج از نوع match$ ایجاد می کنید سپس از طریق اپراتور and$ و اپراتوار eq$ بین دو فیلد inventory.product و  orderApp.products.name را باهم برابر قرارداده و یک رابطه ایجاد می کنیدنکته : توجه شود چون ما در pipeline به فیلد inventory.product دسترسی ندارید از متغیر کمکی که در قسمت let که حاوی مقادیر همین فیلد است بنام products_inventory در pipeline  استفاده می کنید فقط دقت شود برای دسترسی به متغییرهای که در let تعریف شده در قسمت pipeline از دو $$ استفاده می شود{ 
from: &#039;inventory&#039;,
 as: &#039;inventory_product&#039;,
  let:{products_inventory:&amp;quot$product&amp;quot},
    pipeline:[{
    $match:{
      $expr:{$and:[
        {$eq:[&amp;quot$product.name&amp;quot,&amp;quot$$products_inventory&amp;quot]}
      ]}
    }
  }]
} https://www.aparat.com/javadjahangiriniopdc/playlists با تشکر ازمطالعه این مقاله ،مثل همیشه کنجکاو باشید!!!در دوره های آموزش تضمینی مجتمع فنی ارومیه که به صورت خصوصی و عمومی در دو شیوه حضوری و آنلاین برگزار می شود سرفصل های بسیار متنوع و کاربردی را بصورت پروژه محور آموزش داده می شود تا شخص کارآموز بتواند بلافاصله پس از اتمام این دوره در کمترین زمان ممکن وارد بازار کار شود.آموزش تخصص ماست با ما حرفه ای شویدجهت مشاوره با شماره 09149431772 در ارتباط باشید ...</description>
                <category>جواد جهانگیری</category>
                <author>جواد جهانگیری</author>
                <pubDate>Wed, 20 Oct 2021 09:44:35 +0330</pubDate>
            </item>
                    <item>
                <title>آموزش دیتابیس مونگودبی MongoDB Tutorial</title>
                <link>https://virgool.io/@javadjahangiri/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%D8%AF%DB%8C%D8%AA%D8%A7%D8%A8%DB%8C%D8%B3-%D9%85%D9%88%D9%86%DA%AF%D9%88%D8%AF%D8%A8%DB%8C-mongodb-tutorial-incadc7thvtl</link>
                <description>آموزش مونگودبیبه نام آن که جان را فکرت آموخت  /   چراغ دل به نور جان برافروختبا عرض سلام و وقت بخیر خدمت کاربران محترم سایت ویرگول، در این مقاله آموزشی که چکیده آموزش مونگودبی از سایت tutorialspoint  بهمراه مطالب تکمیلی تر , سعی شده یک آموزش کاربردی و پروژه محور از مونگودبی ارایه گردد.ایده این سری مقاله های آموزشی از این موضوع سرچشمه می گیرد که بخشی از خوانندگان وجود دارد که به محتوای نوشتاری آنلاین بهتر پاسخ می دهند و ترجیج می دهند مهارت های جدید را به سرعت از طریق خواندن افزایش دهند.این سری اموزش ها با ارایه اولین پکیج آموزشی در خصوص مانگودبی آغاز می شود که انتظار می رود با واکنش مثبت کاربران همراه شود.توجه: این مقاله به مرور زمان، ویرایش و یا تکمیل می‌شود!تقاضا: در صورتی که با مشکل تایپی، دستوری و یا مفهومی در این مقاله برخورد کردید، از شما دوست عزیز و گرامی، صمیمانه تقاضا می‌کنم که اینجانب را مطلع کرده، تا نسبت به تصحیح و یا تکمیل آن، در اسرع وقت، اقدام نمایم. با کمال تشکر جواد جهانگیریشماره تلفن همراه: 09149431772نشانی پست الکترونیکی: javad.jahangiri.niopdc@gmail.comفیلم‌های آموزشی در آپارات:جواد جهانگیری (CTO) - آپاراتفیلم آموزشی در یوتویب: javad jahangiri - YouTubeنسخه مقاله: ۱.۱ - تاریخ بروزرسانی: 1400/09/09MongoDB - HomeMongoDB Tutorialمونگو یک دیتابیس اوپن سورس و NoSQL می باشد که با زبان C++ برنامه نویسی شده است ما در این اموزش تصمیم داریم بری مفاهیم پایه ای مونگودبی تمرکز داشته باشیم و شما را در ایجاد و استقرار یک پایگاه داده مقایس پذیر و با پرفورمانس بالا کمک کنیمAudienceاین آموزش برای برنامه نویس های که در سطح پیشرفته می باشند طراحی شده است که می خواهند با بیان ساده و آسان با پایگاه داده مونگو دبی آشنا شوند در پایان این سری از اموزش ها شما به سطح متوسطی از تسلط بر روی این پایگاه داده دست خواهید یافتPrerequisitesبرای این اموزش می بایستی یک درک کلی از مفاهیم پایگاه داده را داشته باشید چون در این اموزش ما قصد داریم پایگاه داده ای با کارایی بالا ایجاد کنیم https://www.aparat.com/javadjahangiriniopdc/playlists MongoDB - Overviewمونگودبی یک پایگاه داده مستند گرا و چند پلتفرمی است که عملکرد بالا ، در دسترس بودن بالا و مقیاس پذیری آسان را ارائه می دهد و مونگو دبی روی مفهموم مجموعه و سندکار می کندDatabaseپایگاه داده یک کانتینر فیزیکی برای مجموعه ای از داده ها می باشد. هر پایگاه داده مجموعه فایلهای خاص خود را در سیستم فایل دخیره می کند هر سرور دیتابیس مونگودبی معمولا شامل چندین دتیابیس می باشدCollectionکالکشن در مونگودبی گروه از مستندات مونگودبی می باشد در حقیقت یک کالکشن معادل مفهموم جدول در در دتیابیس های رابطه ای می باشد .هر کالکشن در یک دتیابیس مونگودبی قرار می گیرد و اجباری نیست که کالکشن ها اسکیماهای یکسان داشته باشند .سندهای موجود در هر کالکشن می تواند فیلدهای متفاوتی داشته باشد .بطور معمول ،همه اسناد موجود در یک کالکشن دارای اهداف مشابه و یا مرتبط به هم می باشندDocumentهر سند مجموعه ای از جفت های key-value می باشد.اسناد دارای اسیکما داینامک هستند .اسکیمای پویا به این معنی می باشد که اسناد موجود در یک کالکشن نیازی به مجموعه یکسانی از فیلدها و ساختار ندارند و فیلدهای مشترک در اسناد یک کالکشن ممکن است انواع مختلفی از داده ها را در خود جای دهدجدول زیر رابطه اصطلاحات RDBMS با MongoDB را نشان می دهد.The following table shows the relationship of RDBMS terminology with MongoDBSample Documentمثال زیر ساختار سند یک وب سایت وبلاگی را نشان می دهد ، که به سادگی یک جفت مقدار کلید جدا شده با کاما است.{
   _id: ObjectId(7df78ad8902c)
   title: &#039;MongoDB Overview&#039;, 
   description: &#039;MongoDB is no sql database&#039;,
   by: &#039;tutorials point&#039;,
   url: &#039;http://www.tutorialspoint.com&#039;,
   tags: [&#039;mongodb&#039;, &#039;database&#039;, &#039;NoSQL&#039;],
   likes: 100, 
   comments: [	
      {
         user:&#039;user1&#039;,
         message: &#039;My first comment&#039;,
         dateCreated: new Date(2011,1,20,2,15),
         like: 0 
      },
      {
         user:&#039;user2&#039;,
         message: &#039;My second comments&#039;,
         dateCreated: new Date(2011,1,25,7,45),
         like: 5
      }
   ]
}

ای دی _id یک عدد هگز دسیمال 12 بایتی است که منحصر به فرد بودن هر سند را تضمین می کند در هنگام درج یک سند می توانیم id ان را ارایه کنیم و لی اگر ارایه نشود خود مونگودبی یک شناسه منحصر به فرد بریا هر سند ثبت می کند . این 12 بایت ابتدا 4 بایت ان برای (timestamp) ،سه بایت بعدی برای شناسه ماشین (machine id) ، دو بایت بعدی برای  شناسه پروسس  (process id ) مونگودبی و 3 بایت باقی مانده اخر برای مقدار افزایشی (simple incremental VALUE) می باشدMongoDB - Advantagesهر پایگاه داده رابطه ای معمولا داری یه اسکیمای می باشد که شامل جداول و ارتباط بین این جداول را نشان می دهد در حالی که در مونگودبی (MongoDB) ،مفهومی از رابطه وجود نداردAdvantages of MongoDB over RDBMSعدم نیاز به اسکیمای ثابت     مونگودبی در حقیقت یک پایگاه داده بر پایه اسناد می باشد که در آن یک کالکشن می تواند مستندات مختلفی در خود نگهداری کند. تعداد فیلدها ،محتوا و اندازه سند می تواند از سندی به سند دیگر متفاوت باشد.ساختار هر ابجکت در مانگودبی واحد و واضح می باشدرابطه های پیچیده بین جداول در مانگودبی وجود نداردقابلیت پرس و جوی عمیق    مونگودبی با استفاده از یک زبان پرس و جوی مبتنی بر اسناد که تقریبا به اندازه SQL قوی است ,از کوری های پویا پشتیبانی می کندقابلیت تیونیگ قابلیت مقیاس پذیری راحت       مقیاس بندی در مونگودبی خیلی راحت استتبدیل و نگاشت ابجکت های کاربردی به ابجکت های دیتابیس در مونگودبی مورد نیاز نیستاز حافظه داخلی بعنوان حافظه کاری برای نگهداری داده ها استفاده می کند که این امر دسترسی سریع به داده ها در مونگودبی را فراهم می کندWhy Use MongoDB?ویژگی Document Oriented Storageداده برای اساس فرمت json ذخیره می شودهر صفت و خصوصیت از داده ها قابلیت ایندکس شدن را داردویژگی Replication and high availabilityهمسان سازی اتوماتیک داده ها و بالاترین سطح در دسترس بودن داده ها را پشتیبانی می کندحالت Auto-Sharding  که امکان مقایس پذیری افقی automation of horizontal scaling به مونگودبی می دهدپرس و جوها غنی شدهویژگی Fast in-place updatesیکی از ویژگی های خوب MongoDB این است که به روزرسانی ها می توانند &quot;در محل&quot; اتفاق بیفتند - پایگاه داده نیازی به اختصاص و نوشتن یک نسخه کامل جدید از آبجکت را ندارد.پشتیبانی حرفه ای از توسط تیم مونگودبیWhere to Use MongoDBدر بیگ دیتادر سیستم های مدیریت محتوا در سیستم های موبایل و زیر ساخت های شبکه های اجتماعیدر سیستم های مدیریت داده های کاربریدیتاهاب هابه مجموعه از داده ها از منابع متعدد که برای توزیع ,اشتراک گذاری سازماندهی شده باشد دیتاهاب گفته می شودMongoDB - Environmentاجازه دهید نحوه نصب MongoDB را در ویندوز ببینیم.Install MongoDB On Windowsبرای نصب MongoDB بر روی ویندوز ، ابتدا آخرین نسخه MongoDB را دانلود کنید https://www.mongodb.com/try/download/community جزئیات مورد نیاز را وارد کنید ، برگه Server را انتخاب کنید ، در آن می توانید نسخه MongoDB ، سیستم عامل و بسته بندی را به صورت زیر انتخاب کنید:(پیشنهاد می شود نسخه کامیونیتی برای شروع یادگیری انتخاب شود)اکنون فایل دانلود شده را نصب کنید ، به طور پیش فرض ، در پوشه زیر نصب می شودC:\Program Files\.نکتهدر مراحل نصب با عنایت به اینکه شروع به دانلود MongoDB Compass می کند و از سوی در حدود 160 مگابایت فایل باید دانلود کند و از طرف دیگر این سایت در ایران فیلتر می باشد در حین نصب می بایستی فیلتر شکن فعال باشد و اگر نتوانست در حین مراحل نصب MongoDB Compass دانلود و نصب کند می توانید بصورت دستی ابتدا خودتان از مسیر ذیل این فایل را دانلود و نصب کنید و سپس مراحل نصب سرور کامیونیتی مونگودبی را دوباره انجام دهید و در مراحل نصب تیک MongoDB Compass را برداریدنکتهبرای اینکه برنامه MongoDB Compass کار کند حتما می بایستی بر روی سیستم عامل خودتان Java SE Development Kit نصب شده باشد اگر نصب نیست می توانید از طریق سایت های ایرانی دانلود و نصب کنیدنمایی از برنامه MongoDB Compass را مشاهده می کنید:MongoDB نمایی از برنامه مونگودبی برای ذخیره فایل های خود یک پوشه نیاز دارد مسیر پیش فرض برای ذخیره داده در سیستم عامل های ویندوز C:\data\db  می باشد . بنابراین باید این پوشه را با استفاده Command Prompt ایجاد کنیم برای این کار دستورات زیر را در ترمینال وارد می کنیم:C:\&gt;md data
C:\md data\db
سپس باید تنظیم dbpath را در فهرست ایجاد شده در  فایل mongod.exe را می بایستی تعیین کنید. برای همین ، دستورات زیر را صادر کنیدC:\Users\XYZ&gt;d:cd C:\Program Files\MongoDB\Server\4.2\bin 
C:\Program Files\MongoDB\Server\4.2\bin&gt;mongod.exe --dbpath &amp;quotC:\data&amp;quotاین پیام منتظر اتصالات را در خروجی کنسول  نشان می دهد و روند mongod.exe با موفقیت اجرا می شود. اکنون برای اجرای MongoDB ، باید خط فرمان دیگری را باز کرده و دستور زیر را صادر کنید.C:\Program Files\MongoDB\Server\4.2\bin&gt;mongo.exe
MongoDB shell version v4.2.1
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&amp;gssapiServiceName=mongodb
Implicit session: session { &amp;quotid&amp;quot : UUID(&amp;quot4260beda-f662-4cbe-9bc7-5c1f2242663c&amp;quot) }
MongoDB server version: 4.2.1
&gt;
این نشان می دهد که MongoDB با موفقیت نصب شده و اجرا می شود. دفعه بعد که MongoDB را اجرا می کنید ، فقط باید دستورات را صادر کنیدC:\Program Files\MongoDB\Server\4.2\bin&gt;mongod.exe --dbpath &amp;quotC:\data&amp;quot
C:\Program Files\MongoDB\Server\4.2\bin&gt;mongo.exeپیشنهاد می شود برای سهولت دسترسی به فایل اجرایی پایگاه داده مونگودبی از متغییر محلی ویندوز به متغییر path مسیر دسترسی به پایگاه داده مانگودبی اضافه شودC:\Program Files\MongoDB\Server\4.4\binMongoDB Helpبرای دریافت لیستی از دستورات ، db.help () را در کلاینت MongoDB تایپ کنید. با این کار لیستی از دستورات به شما نشان داده می شود که در تصویر زیر نشان داده شده است. MongoDB Statisticsبرای دریافت آمار در مورد سرور MongoDB ، دستور ()db.stats را در سرویس گیرنده MongoDB تایپ کنید. این نام پایگاه داده ، تعداد مجموعه و اسناد موجود در پایگاه داده را نشان می دهد. خروجی فرمان در تصویر زیر نشان داده شده است. https://www.aparat.com/javadjahangiriniopdc/playlists MongoDB - Data Modellingداده های موجود در MongoDB دارای اسکیمای انعطاف پذیر است. اسناد موجود در یک کالکشن  نیازی به مجموعه ای مشابه از فیلدها یا ساختار را ندارند ، فیلدهای معمولی در اسناد یک کالکشن ممکن است انواع مختلفی از داده ها را در خود جای دهند.Data Model Designمونگودبی دو نوع مدل داده را ارائه می دهند:مدل Embedded و مدل داده Normalized بر اساس الزامات ,هنگام تهیه سند خود می توانید از هر یک از مدل ها استفاده کنیدEmbedded Data Modelدر این مدل ، می توانید تمام داده های مرتبط را در یک سند واحد (embed) کنید ، همچنین به عنوان مدل داده غیر عادی (de-normalized) شناخته می شودبه عنوان مثال ، فرض کنید که ما اطلاعات کارکنان را در سه سند مختلف یعنی Personal_details ، Contact و Address دریافت می کنیم ، می توانید هر سه سند را در یک سند جاسازی کنید ، همانطور که در زیر نشان داده شده است :{
	_id: ,
	Emp_ID: &amp;quot10025AE336&amp;quot
	Personal_details:{
		First_Name: &amp;quotRadhika&amp;quot,
		Last_Name: &amp;quotSharma&amp;quot,
		Date_Of_Birth: &amp;quot1995-09-26&amp;quot
	},
	Contact: {
		e-mail: &amp;quotradhika_sharma.123@gmail.com&amp;quot,
		phone: &amp;quot9848022338&amp;quot
	},
	Address: {
		city: &amp;quotHyderabad&amp;quot,
		Area: &amp;quotMadapur&amp;quot,
		State: &amp;quotTelangana&amp;quot
	}
}Normalized Data Modelدر این مدل ، می توانید اسناد فرعی را در سند اصلی با استفاده از منابع ارجاع دهید. به عنوان مثال ، می توانید سند فوق را در مدل نرمال شده دوباره بنویسید:Employee:{
	_id: &lt;ObjectId101&gt;,
	Emp_ID: &amp;quot10025AE336&amp;quot
}Personal_details:{
	_id: &lt;ObjectId102&gt;,
	empDocID: &amp;quot ObjectId101&amp;quot,
	First_Name: &amp;quotRadhika&amp;quot,
	Last_Name: &amp;quotSharma&amp;quot,
	Date_Of_Birth: &amp;quot1995-09-26&amp;quot
}Contact:{
	_id: &lt;ObjectId103&gt;,
	empDocID: &amp;quot ObjectId101&amp;quot,
	e-mail: &amp;quotradhika_sharma.123@gmail.com&amp;quot,
	phone: &amp;quot9848022338&amp;quot
}Address:{
	_id: &lt;ObjectId104&gt;,
	empDocID: &amp;quot ObjectId101&amp;quot,
	city: &amp;quotHyderabad&amp;quot,
	Area: &amp;quotMadapur&amp;quot,
	State: &amp;quotTelangana&amp;quot
}نکاتی در هنگام طراحی Schema در MongoDBاسکیمای خود را با توجه به نیازهای کاربر طراحی کنید.اگر اشیاء را با هم استفاده کنید ، آنها را در یک سند ترکیب کنید. در غیر این صورت آنها را جدا کنید (اما مطمئن شوید که نیازی به پیوستن نیست)داده ها را کپی کنید (اما محدود) زیرا فضای دیسک در مقایسه با زمان محاسبه ارزان استهنگام نوشتن Join کنید ، نه هنگام خواندناسکیمای خود را برای اغلب موارد استفاده بهینه کنیداز تجمیع های پیچیده  در اسکیمای خود استفاده کنیدExampleفرض کنید یک مشتری برای وبلاگ خود به طراحی پایگاه داده نیاز دارد:هر پست عنوان ، توضیحات و آدرس اینترنتی منحصر به فردی دارد.هر پست می تواند یک یا چند برچسب داشته باشدهر پست نام ناشر و تعداد کل لایک ها را داردهر پست دارای نظراتی است که کاربران به همراه نام ، پیام ، زمان داده و لایک آنها ارائه می دهنددر هر پست ، می تواند صفر یا بیشتر نظرات داشته باشددر اسکیمای RDBMS ، طراحی برای الزامات فوق حداقل سه جدول خواهد داشت.در حالی که در اسکیمایMongoDB ، ما یک کالکشن (collection)  پست (post) با ساختار زیر خواهد بود:{
   _id: POST_ID
   title: TITLE_OF_POST, 
   description: POST_DESCRIPTION,
   by: POST_BY,
   url: URL_OF_POST,
   tags: [TAG1, TAG2, TAG3],
   likes: TOTAL_LIKES, 
   comments: [	
      {
         user:&#039;COMMENT_BY&#039;,
         message: TEXT,
         dateCreated: DATE_TIME,
         like: LIKES 
      },
      {
         user:&#039;COMMENT_BY&#039;,
         message: TEXT,
         dateCreated: DATE_TIME,
         like: LIKES
      }
   ]
}بنابراین هنگام نمایش داده ها ، در RDBMS شما باید به سه جدول بپیوندید و در MongoDB ، داده ها فقط از یک کالکشن (collection) نشان داده می شوند. https://www.aparat.com/javadjahangiriniopdc/playlists MongoDB - Create Databaseدر این فصل نحوه ایجاد پایگاه داده در MongoDB را خواهیم دید.The use Commandمونگودبی از DATABASE_NAME برای ایجاد پایگاه داده استفاده می کند ای دستور یک دیتابیس جدید می سازد در صورتی که وجود نداشته باشد و درغیر اینصورت اطلاعات دیتابیس موجود را برگشت می دهدSyntaxشکل دستوری استفاده از دستور use DATABASE به شرح زیر است:use DATABASE_NAMEExampleاگر می خواهید از پایگاه داده ای با نام &lt;mydb&gt; استفاده کنید ، عبارت DATABASE به شرح زیر است:&gt;use mydb
switched to db mydbبرای بررسی پایگاه داده انتخاب شده خود ، از دستور db استفاده کنید:&gt;db
mydbاگر می خواهید لیست پایگاه های داده خود را بررسی کنید ، از دستور show dbs استفاده کنید:&gt;show dbs
local     0.78125GB
test      0.23012GBپایگاه داده ایجاد شده شما (mydb) در لیست موجود نیست. برای نمایش پایگاه داده ، باید حداقل یک سند را در آن وارد کنید.&gt;db.movie.insert({&amp;quotname&amp;quot:&amp;quottutorials point&amp;quot})
&gt;show dbs
local      0.78125GB
mydb       0.23012GB
test       0.23012GBدر پایگاه داده MongoDB دیتابیس پیش فرض test می باشد. اگر هیچ پایگاه داده ای ایجاد نکرده اید ، collections ها در پایگاه داده test ذخیره می شوند.MongoDB - Drop Databaseدر این فصل نحوه drop کردن پایگاه داده با استفاده از فرمان MongoDB را خواهیم دید.The dropDatabase() Methodدستور ()db.dropDatabase برای حذف کردن پایگاه داده موجود استفاده می شود.Syntaxشکل دستوری ()dropDatabase به شرح زیر است:db.dropDatabase()با این کار پایگاه داده انتخاب شده حذف می شود. اگر هیچ پایگاه داده ای را انتخاب نکرده اید ، پایگاه داده پیش فرض &quot;test&quot; را حذف می کند.Example&gt;show dbs
local      0.78125GB
mydb       0.23012GB
test       0.23012GB
&gt;اگر می خواهید پایگاه داده جدید &lt;mydb&gt; را حذف کنید ، دستور ()dropDatabase به شرح زیر است:&gt;use mydb
switched to db mydb
&gt;db.dropDatabase()
&gt;{ &amp;quotdropped&amp;quot : &amp;quotmydb&amp;quot, &amp;quotok&amp;quot : 1 }
&gt;اکنون لیست پایگاه های داده را بررسی کنید.&gt;show dbs
local      0.78125GB
test       0.23012GB
&gt;MongoDB - Create Collectionدر این فصل نحوه ایجاد Collection با استفاده از MongoDB را خواهیم دید.The createCollection() MethodMongoDB db.createCollection(name, options) is used to create collection.Syntaxdb.createCollection(name, options)در این دستور ، name نام کالکشن است که باید ایجاد شود. Options یک سند است و برای تعیین پیکربندی کالکشن ها مورد استفاده قرار می گیردپارامتر Options اختیاری است ، بنابراین باید فقط نام کالکشن را مشخص کنید. در زیر لیستی از گزینه هایی است که می توانید استفاده کنید:هنگام درج سند ، MongoDB ابتدا فیلد اندازه capped collection را بررسی می کند ، سپس max field را بررسی می کند.Examplesشکل دستوری روش ()createCollection بدون options به شرح زیر است -&gt;use test
switched to db test
&gt;db.createCollection(&amp;quotmycollection&amp;quot)
{ &amp;quotok&amp;quot : 1 }
&gt;با استفاده از دستور show collections می توانید کالکشن ایجاد شده را بررسی کنید:&gt;show collections
mycollection
system.indexesمثال زیر نحو متد ()createCollection را با چند گزینه مهم نشان می دهد -&gt; db.createCollection(&amp;quotmycol&amp;quot, { capped : true, autoIndexID : true, size : 6142800, max : 10000 } ){
&amp;quotok&amp;quot : 0,
&amp;quoterrmsg&amp;quot : &amp;quotBSON field &#039;create.autoIndexID&#039; is an unknown field.&amp;quot,
&amp;quotcode&amp;quot : 40415,
&amp;quotcodeName&amp;quot : &amp;quotLocation40415&amp;quot
}
&gt;در MongoDB ، نیازی به ایجاد کالکشن ندارید. هنگام وارد کردن سند ، MongoDB به طور خودکار مجموعه ایجاد می کند&gt;db.tutorialspoint.insert({&amp;quotname&amp;quot : &amp;quottutorialspoint&amp;quot})
WriteResult({ &amp;quotnInserted&amp;quot : 1 })
&gt;show collections
mycol
mycollection
system.indexes
tutorialspoint
&gt;در مثال بالا توجه کنید db.tutorialspoint.insert اسم کالکشن که باید ایجاد شود tutorialspoint می باشد که شامل سندی است که در ان فیلد name  با مقدار tutorialspoint می باشدMongoDB - Drop Collectionاستفاده از متد ()drop در MongoDB :دستور ()db.collection.drop در MongoDB  برای حذف یک مجموعه از پایگاه داده استفاده می شود.یک مجموعه یا نمایش را از پایگاه داده حذف می کند.این متد همچنین هر شاخصی را که مربوط به مجموعه پاک شده است را نیز حذف می کند.سینتکسدستورالعمل پایه دستور() drop در MongoDB به شرح زیر است:1db.COLLECTION_NAME.drop()مثالابتدا باید، مجموعه های موجود را در پایگاه داده mydb بررسی کنید.دستور آن به شکل زیر است :&gt;use mydb
switched to db mydb
&gt;show collections
mycol
mycollection
system.indexes
tutorialspoint&gt;سپس مجموعه mycollection را حذف نمایید:&gt;db.mycollection.drop()
true
&gt;مجددا لیستی از مجموعه ها را در پایگاه داده چک کنید.&gt;show collections
mycol
system.indexes
tutorialspoint
&gt;اگر مجموعه انتخاب شده با موفقیت حذف شود، متد ()drop  مقدار درست را بازگرداند، در غیر اینصورت، مقدار غلط برگشت داده خواهد شد.این روش بر قفل نوشتن بر روی پایگاه داده آسیب می زند و دیگر عملیات نوشتن را تا زمانی که تمام نشده است، مسدود کند.حذف و ایجاد مجموعه در MongoDB از اعمال پر کاربرد در این پایگاه داده می باشد.امیدوارم از مطالب مذکور بهره کافی را برده باشید با ما همراه باشید تا در جلسه بعد انواع داده ها را در MongoDB بشناسید.MongoDB - Datatypesبه طور کلی داده هایی که در MongoDB می توانید وارد کنید شامل انواع زیر می شوند:داده متنیداده عددیداده تاریخ و زمانMongoDB از بسیاری از انواع داده پشتیبانی می کند. برخی از آنها در زیر لیست شده اند :String : این نوع داده معمولی است که برای ذخیره داده ها استفاده می شود. رشته در MongoDB باید توسط UTF-8 معتبر باشد.Integer : این نوع برای ذخیره یک مقدار عددی استفاده می شود. Integer می تواند ۳۲ بیتی یا ۶۴ بیتی بسته به سرور شما باشد.Boolean : این نوع برای ذخیره یک مقدار (true / false) استفاده می شود.Double : این نوع برای ذخیره مقادیر شناور و اعشاری استفاده می شود.Min/ Max keys : این نوع برای مقایسه مقادیر علیه کمترین و بالاترین عناصر BSON استفاده می شود.Arrays : این نوع برای ذخیره آرایه ها یا لیست ها یا مقادیر متعدد در یک کلید استفاده می شود.Timestamp-ctimestamp : می تواند برای ضبط هنگامی که یک سند اصلاح شده یا اضافه شده است مفید باشد.Object : این نوع داده برای اسناد جاسازی شده استفاده می شود.Null : این نوع برای ذخیره یک مقدار Null استفاده می شود.Symbol : این نوع داده با یک رشته به طور یکسان استفاده می شود. با این حال، به طور کلی برای زبان هایی که از یک نوع نماد خاص استفاده می کنند، استفاده می شود.date : این نوع داده برای ذخیره تاریخ یا زمان فعلی در فرمت زمان بندی یونیکس استفاده می شود. شما می توانید زمان تاریخ خود را با ایجاد شیء تاریخ و گذراندن روز، ماه، سال به آن مشخص کنید.Object ID : این نوع داده برای ذخیره شناسه سند استفاده می شود.داده باینری : این نوع داده برای ذخیره اطلاعات باینری استفاده می شود.Code : این نوع داده برای ذخیره ی جاوا اسکریپت در سند استفاده می شود.عبارت Regular : این نوع داده برای ذخیره عبارات منظم استفاده می شود.۱۵ نوع از انواع داده های MongoDB که در این پایگاه داده پشتیبانی می شدند را نام بردیم. درج سند در MongoDB آموزش بعدی ما خواهد بود،با ما همراه باشید.MongoDB - Insert Documentدر این فصل، ما نحوه قرار دادن سند در مجموعه MongoDB یاد می گیریم.برای ساخت سند باید از دستور insert استفاده شود:برای قرار دادن داده ها در مجموعه MongoDB، شما باید از ()insert یا ()save در MongoDB استفاده کنید.سینتکسدستورالعمل اولیه دستور ()insert به شرح زیر است:db.COLLECTION_NAME.insert(document)
&gt;db.mycol.insert({
   _id: ObjectId(7df78ad8902c),
   title: &#039;MongoDB Overview&#039;, 
   description: &#039;MongoDB is no sql database&#039;,
   by: &#039;tutorials point&#039;,
   url: &#039;http://www.tutorialspoint.com&#039;,
   tags: [&#039;mongodb&#039;, &#039;database&#039;, &#039;NoSQL&#039;],
   likes: 100
})در اینجا mycol نام مجموعه ما است، همانطور که در فصل قبل ایجاد کردیم. اگر مجموعه موجود در پایگاه داده وجود نداشته باشد، MongoDB این مجموعه را ایجاد می کند و سپس یک سند را وارد آن می کند.در سند وارد شده، اگر id parameter_ را مشخص نکنیم،مانگو  ObjectId منحصر به فرد را برای این سند اختصاص می دهد.id _ از ۱۲ بایت  هگزادسیمال منحصر به فرد برای هر سند در یک مجموعه استفاده می کند.۱۲ بایت به صورت زیر تقسیم می شوند:مثال:_id: ObjectId(4 bytes timestamp, 3 bytes machine id, 2 bytes process id,   3 bytes incrementer)برای قرار دادن اسناد متعدد در یک کوئری تنها می توانید یک آرایه ای از اسناد را در دستور insert () منتقل کنید.&gt;db.post.insert([
   {
      title: &#039;MongoDB Overview&#039;, 
      description: &#039;MongoDB is no sql database&#039;,
      by: &#039;tutorials point&#039;,
      url: &#039;http://www.tutorialspoint.com&#039;,
      tags: [&#039;mongodb&#039;, &#039;database&#039;, &#039;NoSQL&#039;],
      likes: 100
   },
 {
      title: &#039;NoSQL Database&#039;, 
      description: &amp;quotNoSQL database doesn&#039;t have tables&amp;quot,
      by: &#039;tutorials point&#039;,
      url: &#039;http://www.tutorialspoint.com&#039;,
      tags: [&#039;mongodb&#039;, &#039;database&#039;, &#039;NoSQL&#039;],
      likes: 20, 
      comments: [	
         {
            user:&#039;user1&#039;,
            message: &#039;My first comment&#039;,
            dateCreated: new Date(2013,11,10,2,35),
            like: 0 
         }
      ]
   }
])در نسخه جدید ۳٫۲ وارد کردن اسناد چندگانه در MongoDB نیز افزوده شده…با دستور ()db.collection.insertMany  می توانید چندین اسناد را در مجموعه قرار دهید. و بدی صورت آرایه ای از مدارک را با این روش انتقال دهید.برای وارد کردن سند می توانید از(سند) db.post.save نیز استفاده کنید. اگر _id را در سند مشخص نکنید، روش () Save  همانند روش () insert کار خواهد کرد.MongoDB - Query Documentاستفاده از متد ()find  :برای پرس و جو داده ها از مجموعه MongoDB، شما باید از متد () find  در MongoDB استفاده کنید.سینتکس اصلی متد ()find به شرح زیر است:&gt;db.COLLECTION_NAME.find()متد ()prettyبرای نمایش نتایج در قالب فرمت شده، شما می توانید از متد ()pretty با سینتکس زیر استفاده کنید :&gt;db.mycol.find().pretty()مثال&gt;db.mycol.find().pretty(){
   &amp;quot_id&amp;quot: ObjectId(7df78ad8902c),
   &amp;quottitle&amp;quot: &amp;quotMongoDB Overview&amp;quot, 
   &amp;quotdescription&amp;quot: &amp;quotMongoDB is no sql database&amp;quot,
   &amp;quotby&amp;quot: &amp;quottutorials point&amp;quot,
   &amp;quoturl&amp;quot: &amp;quothttp://www.tutorialspoint.com&amp;quot,
   &amp;quottags&amp;quot: [&amp;quotmongodb&amp;quot, &amp;quotdatabase&amp;quot, &amp;quotNoSQL&amp;quot],
   &amp;quotlikes&amp;quot: &amp;quot100&amp;quot
}
&gt;به غیر از متد ()find ، متد ()findOne نیز وجود دارد که تنها یک سند را باز می گرداند.برای کوئری سند بر اساس برخی شرایط، می توانید از عملیات زیر استفاده کنید.AND در MongoDBدر متد  () find اگر کلید های چندگانه را توسط علامت ‘,’ از هم جدا کنید، در MongoDB مشابه عملگر AND عمل میکند.مثال :&gt;db.mycol.find(
   {
      $and: [
         {key1: value1}, {key2:value2}
      ]
   }
).pretty()OR در MongoDBبرای کوئری  مدارک بر اساس شرایط OR، شما باید از کلمه کلیدی OR$  استفاده کنید.در مثال زیر سینتکس  OR نشان داده شده است :&gt;db.mycol.find(
   {
      $or: [
         {key1: value1}, {key2:value2}
      ]
   }
).pretty()مثال زیر همه آموزش هایی که توسط ‘tutorials point’ نوشته شده یا عنوان آن ‘MongoDB Overview’ را نشان می دهد.&gt;db.mycol.find({$or:[{&amp;quotby&amp;quot:&amp;quottutorials point&amp;quot},{&amp;quottitle&amp;quot: &amp;quotMongoDB Overview&amp;quot}]}).pretty()
{
   &amp;quot_id&amp;quot: ObjectId(7df78ad8902c),
   &amp;quottitle&amp;quot: &amp;quotMongoDB Overview&amp;quot, 
   &amp;quotdescription&amp;quot: &amp;quotMongoDB is no sql database&amp;quot,
   &amp;quotby&amp;quot: &amp;quottutorials point&amp;quot,
   &amp;quoturl&amp;quot: &amp;quothttp://www.tutorialspoint.com&amp;quot,
   &amp;quottags&amp;quot: [&amp;quotmongodb&amp;quot, &amp;quotdatabase&amp;quot, &amp;quotNoSQL&amp;quot],
   &amp;quotlikes&amp;quot: &amp;quot100&amp;quot
}
&gt;استفاده از AND و OR با هممثال زیر اسنادی را به ما نشان می دهد که مقدار likes بالاتر از ۱۰ است و عنوان آنها ‘MongoDB Overview’ یا ‘tutorials point’ می باشد.‘where likes&gt;10 AND (by = ‘tutorials point’ OR title = ‘MongoDB Overview’)’سینتکس در SQL&gt;db.mycol.find({&amp;quotlikes&amp;quot: {$gt:10}, $or: [{&amp;quotby&amp;quot: &amp;quottutorials point&amp;quot},
   {&amp;quottitle&amp;quot: &amp;quotMongoDB Overview&amp;quot}]}).pretty()
{
   &amp;quot_id&amp;quot: ObjectId(7df78ad8902c),
   &amp;quottitle&amp;quot: &amp;quotMongoDB Overview&amp;quot, 
   &amp;quotdescription&amp;quot: &amp;quotMongoDB is no sql database&amp;quot,
   &amp;quotby&amp;quot: &amp;quottutorials point&amp;quot,
   &amp;quoturl&amp;quot: &amp;quothttp://www.tutorialspoint.com&amp;quot,
   &amp;quottags&amp;quot: [&amp;quotmongodb&amp;quot, &amp;quotdatabase&amp;quot, &amp;quotNoSQL&amp;quot],
   &amp;quotlikes&amp;quot: &amp;quot100&amp;quot
}
&gt;توجه داشته باشید متد ()find تمام اسناد را به صورت غیر ساختاری نمایش می دهد و برای نمایش نتایج در قالب فرمت شده، شما باید از متد ()pretty استفاده نمایید.MongoDB - Update Documentتدهای ()update  و ()save  در MongoDB برای به روز رسانی سند در یک مجموعه استفاده می شود.متد ()update  مقادیر موجود در سند موجود را بروز رسانی می کند در حالی که متد ()Save  جایگزین سند موجود با سند منتقل شده در روش ()save  می شود.متد ()Update در MongoDBمتد ()update مقادیر موجود در سندهای موجود را بروز رسانی می کند.سینتکسسینکس اصلی متد ()update به صورت زیر است :&gt;db.COLLECTION_NAME.update(SELECTION_CRITERIA, UPDATED_DATA)مثالفرض کنید مجموعه mycol دارای داده های زیر است.{ &amp;quot_id&amp;quot : ObjectId(5983548781331adf45ec5), &amp;quottitle&amp;quot:&amp;quotMongoDB Overview&amp;quot}
{ &amp;quot_id&amp;quot : ObjectId(5983548781331adf45ec6), &amp;quottitle&amp;quot:&amp;quotNoSQL Overview&amp;quot}
{ &amp;quot_id&amp;quot : ObjectId(5983548781331adf45ec7), &amp;quottitle&amp;quot:&amp;quotTutorials Point Overview&amp;quot}مثال زیر تایتل جدید سندها را با عنوان ‘New MongoDB Tutorial’ برای سندهایی که تایتل آنها ‘MongoDB Overview’ است تنظیم می کند.&gt;db.mycol.update({&#039;title&#039;:&#039;MongoDB Overview&#039;},{$set:{&#039;title&#039;:&#039;New MongoDB Tutorial&#039;}})
WriteResult({ &amp;quotnMatched&amp;quot : 1, &amp;quotnUpserted&amp;quot : 0, &amp;quotnModified&amp;quot : 1 })
&gt;db.mycol.find()
{ &amp;quot_id&amp;quot : ObjectId(5983548781331adf45ec5), &amp;quottitle&amp;quot:&amp;quotNew MongoDB Tutorial&amp;quot}
{ &amp;quot_id&amp;quot : ObjectId(5983548781331adf45ec6), &amp;quottitle&amp;quot:&amp;quotNoSQL Overview&amp;quot}
{ &amp;quot_id&amp;quot : ObjectId(5983548781331adf45ec7), &amp;quottitle&amp;quot:&amp;quotTutorials Point Overview&amp;quot}
&gt;به طور پیش فرض، MongoDB فقط یک سند تک  را بروز رسانی می کند. برای بروز رسانی چندین اسناد، شما باید پارامتر ‘multi’ را به درست تنظیم کنید.&gt;db.mycol.update({&#039;title&#039;:&#039;MongoDB Overview&#039;},
   {$set:{&#039;title&#039;:&#039;New MongoDB Tutorial&#039;}},{multi:true})متد ()save در MongoDBمتد ()save  سند موجود را با سند جدیدی که در روش ()save منتقل شده است جایگزین می کند.سینتکسسینتکس اصلی متد ()save در MongoDB در زیر نشان داده شده است :&gt;db.COLLECTION_NAME.save({_id:ObjectId(),NEW_DATA})مثالدر مثال زیر سند با آیدی_ ‘۵۹۸۳۵۴۸۷۸۱۳۳۱adf45ec5 جایگزین خواهد شد.&gt;db.mycol.save(
   {
      &amp;quot_id&amp;quot : ObjectId(5983548781331adf45ec5), &amp;quottitle&amp;quot:&amp;quotTutorials Point New Topic&amp;quot,
      &amp;quotby&amp;quot:&amp;quotTutorials Point&amp;quot
   }
)
&gt;db.mycol.find()
{ &amp;quot_id&amp;quot : ObjectId(5983548781331adf45ec5), &amp;quottitle&amp;quot:&amp;quotTutorials Point New Topic&amp;quot,
   &amp;quotby&amp;quot:&amp;quotTutorials Point&amp;quot}
{ &amp;quot_id&amp;quot : ObjectId(5983548781331adf45ec6), &amp;quottitle&amp;quot:&amp;quotNoSQL Overview&amp;quot}
{ &amp;quot_id&amp;quot : ObjectId(5983548781331adf45ec7), &amp;quottitle&amp;quot:&amp;quotTutorials Point Overview&amp;quot}
&gt;بروز رسانی سند در MongoDB توسط متدهای ()update  و ()save صورت می پذیرد.ولی هرکدام ازین متدها نیز برای کاربرد خاصی استفاده می شوند.امیدوارم از مطالب ذکر شده بهره کافی را برده باشید.در جلسه بعدی حذف سند در MongoDB آموزش داده خواهد شد.MongoDB - Delete Documentهمانطور که گفته شد متد ()remove در MongoDB برای حذف یک سند از مجموعه استفاده می شود. این متد دو پارامتر را می پذیرد.یکی از آن ها معیارهای حذف است و دومی  پرچم justOne است.معیار حذف (اختیاری) :  معیارهای حذف با توجه به اسناد حذف خواهند شد.justOne (اختیاری) : اگر مقدار درست یا ۱ تنظیم شود،تنها یک سند را حذف کنید.سینتکسسینتکس اصلی متد ()remove به شرح زیر می باشد :&gt;db.COLLECTION_NAME.remove(DELLETION_CRITTERIA)
فرض کنید مجموعه mycol دارای داده های زیر است.{ &amp;quot_id&amp;quot : ObjectId(5983548781331adf45ec5), &amp;quottitle&amp;quot:&amp;quotMongoDB Overview&amp;quot}
{ &amp;quot_id&amp;quot : ObjectId(5983548781331adf45ec6), &amp;quottitle&amp;quot:&amp;quotNoSQL Overview&amp;quot}
{ &amp;quot_id&amp;quot : ObjectId(5983548781331adf45ec7), &amp;quottitle&amp;quot:&amp;quotTutorials Point Overview&amp;quot}مثال زیر تمام اسنادهایی را که عنوان آن ها “Overview MongoDB” است حذف می کند.&gt;db.mycol.remove({&#039;title&#039;:&#039;MongoDB Overview&#039;})
&gt;db.mycol.find()
{ &amp;quot_id&amp;quot : ObjectId(5983548781331adf45ec6), &amp;quottitle&amp;quot:&amp;quotNoSQL Overview&amp;quot}
{ &amp;quot_id&amp;quot : ObjectId(5983548781331adf45ec7), &amp;quottitle&amp;quot:&amp;quotTutorials Point Overview&amp;quot}
&gt;حذف تکیاگر چندین رکورد وجود داشته باشد و شما بخواهید اولین رکورد را حذف نمایید،باید پارامتر justOne را در متد ()remove تنظیم کنید.&gt;db.COLLECTION_NAME.remove(DELETION_CRITERIA,1)حذف تمام اسناداگر معیارهای حذف را مشخص نکنید، MongoDB تمام مدارک را از مجموعه حذف خواهد کرد. و معادل دستور فرمان SQL است.&gt;db.mycol.remove()
&gt;db.mycol.find()
&gt;MongoDB - Projectionدر MongoDB، طرح ریزی به معنی انتخاب اطلاعات لازم است تا انتخاب کل داده های یک سند.یعنی اگر یک سند دارای ۵ فیلد باشد و شما بخواهید تنها همان ۳ را فیلد را نمایش دهید، پس بتوانید فقط ۳ فیلد را از آنها انتخاب کنید.متد ()findمتد ()find در  MongoDB قبلا توضیح داده شده و برای پرس و جو استفاده می شود.این متد دو پارامتر اختیاری را می پذیرد که لیستی از فیلدهایی است که می خواهید آن ها را بازیابی کنید.در MongoDB، هنگام اجرای متد ()find، تمام فیلدهای یک سند نمایش داده می شود.برای محدود کردن آن، شما نیاز به تنظیم یک لیست از فیلدها با مقدار ۱ یا ۰٫ ۱ برای نشان دادن فیلد استفاده می شود در حالی که ۰ برای مخفی کردن فیلدها استفاده می شود.سینتکس پایه متد ()find برای طرح ریزی به شرح زیر است:&gt;db.COLLECTION_NAME.find({},{KEY:1})فرض کنید مجموعه mycol دارای داده های زیر است :{ &amp;quot_id&amp;quot : ObjectId(5983548781331adf45ec5), &amp;quottitle&amp;quot:&amp;quotMongoDB Overview&amp;quot}
{ &amp;quot_id&amp;quot : ObjectId(5983548781331adf45ec6), &amp;quottitle&amp;quot:&amp;quotNoSQL Overview&amp;quot}
{ &amp;quot_id&amp;quot : ObjectId(5983548781331adf45ec7), &amp;quottitle&amp;quot:&amp;quotTutorials Point Overview&amp;quot}مثال زیر، عنوان سند را هنگام جستجو در سند نمایش می دهد.&gt;db.mycol.find({},{&amp;quottitle&amp;quot:1,_id:0})
{&amp;quottitle&amp;quot:&amp;quotMongoDB Overview&amp;quot}
{&amp;quottitle&amp;quot:&amp;quotNoSQL Overview&amp;quot}
{&amp;quottitle&amp;quot:&amp;quotTutorials Point Overview&amp;quot}
&gt;نکتهدر هنگام اجرای متد ()find ، فیلد _id همیشه نمایش داده شود، اگر شما این فیلد را نمی خواهید، باید آن را ۰ قرار دهید.پرس و جو در MongoDB توسط متد ()find صورت می گیرد.در MongoDB، هنگامی که یک مجموعه را با استفاده از متد ()db.collection.find  جستجو می کنید، می توانید مشخص کنید کدام فیلدها را که می خواهید برگردانید.همچنین شما می توانید این کار را با وارد کردن نام فیلد در پرس و جو و اضافه کردن ۱ یا ۰ در کنار آن انجام دهید تا مشخص شود آیا باید آن را بازگردانده شود یا خیر.MongoDB - Limit Recordsمتد ()Limitبرای محدود کردن رکوردها در MongoDB، شما باید از متد ()Limit  استفاده کنید. این متد یک آرگومان از نوع عددی را می پذیرد، که نشان دهنده تعداد اسنادی است که می خواهید نمایش داده شوند.سینتکس پایه برای متد ()Limit به صورت زیر می باشد:&gt;db.COLLECTION_NAME.find().limit(NUMBER)فرض کنید مجموعه myycol دارای داده های زیر است.{ &amp;quot_id&amp;quot : ObjectId(5983548781331adf45ec5), &amp;quottitle&amp;quot:&amp;quotMongoDB Overview&amp;quot}
{ &amp;quot_id&amp;quot : ObjectId(5983548781331adf45ec6), &amp;quottitle&amp;quot:&amp;quotNoSQL Overview&amp;quot}
{ &amp;quot_id&amp;quot : ObjectId(5983548781331adf45ec7), &amp;quottitle&amp;quot:&amp;quotTutorials Point Overview&amp;quot}در مثال زیر، هنگام جستجو در سند، تنها دو سند نمایش داده خواهد شد.&gt;db.mycol.find({},{&amp;quottitle&amp;quot:1,_id:0}).limit(2)
{&amp;quottitle&amp;quot:&amp;quotMongoDB Overview&amp;quot}
{&amp;quottitle&amp;quot:&amp;quotNoSQL Overview&amp;quot}
&gt;گر شماره آرگومان را در متد ()Limit مشخص نکنید، تمام اسنادمجموعه نمایش داده می شود.متد ()skipبه غیر از متد ()Limit، یک متد دیگر ()skip وجود دارد که  آرگومان از نوع عددی را می پذیرد و برای تعداد اسناد استفاده می شود.سینتکس این متد به صورت زیر می باشد :&gt;db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER)مثالدر مثال زیر تنها دومین سند نمایش داده می شود.&gt;db.mycol.find({},{&amp;quottitle&amp;quot:1,_id:0}).limit(1).skip(1)
{&amp;quottitle&amp;quot:&amp;quotNoSQL Overview&amp;quot}
&gt;توجه داشته باشید، مقدار پیش فرض در متد ()skip صفر  است.هنگامی که ما یک مجموعه را فراخوانی می کنیم، همه اسناد موجود در آن را نمایش داده می شود. محدودیت برای بازیابی تعداد اسنادی است که ما نیاز داریم از آنها استفاده کنیم. ما می توانیم از متد limit در MongoDB  برای مشخص کردن تعداد اسنادی که می خواهیم آن را بازگردانیم استفاده کنیم.محدودیت رکورد ها در MongoDB توسط توسط متدهای  ()Limit  و ()skip به پایان رسید در جلسه بعدی مرتب سازی رکورد ها در در MongoDB را آموزش خواهیم دادMongoDB - Sort Recordsاستفاده از متد ()sortبرای مرتب کردن اسناد در MongoDB، شما باید از متد ()sort استفاده کنید. این متد یک سند حاوی لیستی از فیلدها همراه با دستور مرتب سازی آنها را می پذیرد. برای مشخص کردن مرتبه مرتب سازی ۱ و -۱ استفاده می شود. ۱ به منظور مرتب سازی صعودی استفاده می شود در حالی که ۱- برای ترتیب نزولی استفاده می شود.هنگام مقایسه مقادیر انواع مختلف BSON،در  MongoDB از ترتیب مقایسه زیر استفاده می شود( از کمترین به بالاترین):MinKey (نوع داخلی)Nullاعدادنماد، رشتههدف – شیآرایهBinDataObjectIdبولینتاریخTimestampعبارت منظمMaxKey (نوع داخلی)سینتکسفرم اولیه sort بصورت زیر است :{ $sort: { &lt;field1&gt;: &lt;sort order&gt;, &lt;field2&gt;: &lt;sort order&gt; ... } }سینتکس متد ()sort در MongoDB به شرح زیر است :&gt;db.COLLECTION_NAME.find().sort({KEY:1})مثالفرض کنید مجموعه myycol دارای داده های زیر است.{ &amp;quot_id&amp;quot : ObjectId(5983548781331adf45ec5), &amp;quottitle&amp;quot:&amp;quotMongoDB Overview&amp;quot}
{ &amp;quot_id&amp;quot : ObjectId(5983548781331adf45ec6), &amp;quottitle&amp;quot:&amp;quotNoSQL Overview&amp;quot}
{ &amp;quot_id&amp;quot : ObjectId(5983548781331adf45ec7), &amp;quottitle&amp;quot:&amp;quotTutorials Point Overview&amp;quot}مثال زیر اسناد مرتب شده بر اساس عنوان(title) را در ترتیب نزولی به شما نشان می دهد.&gt;db.mycol.find({},{&amp;quottitle&amp;quot:1,_id:0}).sort({&amp;quottitle&amp;quot:-1})
{&amp;quottitle&amp;quot:&amp;quotTutorials Point Overview&amp;quot}
{&amp;quottitle&amp;quot:&amp;quotNoSQL Overview&amp;quot}
{&amp;quottitle&amp;quot:&amp;quotMongoDB Overview&amp;quot}
&gt;لطفا توجه داشته باشید اگر ترتیب صعودی یا نزولی بودن را مشخص نکنید، درنتیجه متد ()sort در MongoDB اسناد را به ترتیب صعودی نمایش می دهد.با ما همراه باشید تا در جلسه بعد فهرست کردن در MongoDB را فرا بگیرید.MongoDB - Indexingایندکس‌ها در MongoDB تاثیر بسیاری در اجرای کوئری‌ها دارند.بدون ایندکس‌ها، MongoDB باید تمام سندهای یک مجموعه را برای انتخاب سندهایی که با عبارت کوئری مطابقت دارند، اسکن کند.این اسکن بسیار ناکارآمد است و در این حالت mongoDB به پردازش حجم بزرگی از داده‌ها نیاز دارد.متد ()createIndexبرای ساخت ایندکس‌ها در MongoDB باید از متد ()createIndexاستفاده کنید.سینتکسسینتکس پایه متد ()createIndex به شکل زیر است:&gt;db.COLLECTION_NAME.createIndex({KEY:1})در اینجا، key نام فیلدی است که می‌خواهید بر روی آن ایندکس بسازید و مقدار ۱ برای مرتب سازی بصورت صعودی است.برای ساخت ایندکس‌ها در MongoDB با مرتب سازی نزولی باید از مقدار ۱- استفاده کنید.مثال:&gt;db.mycol.createIndex({&amp;quottitle&amp;quot:1})
{
	&amp;quotcreatedCollectionAutomatically&amp;quot : false,
	&amp;quotnumIndexesBefore&amp;quot : 1,
	&amp;quotnumIndexesAfter&amp;quot : 2,
	&amp;quotok&amp;quot : 1
}
&gt;در متد ()createIndex برای ساخت ایندکس بر روی چندین فیلد، می‌توانید چندین فیلد را به آن پاس دهید:&gt;db.mycol.createIndex({&amp;quottitle&amp;quot:1,&amp;quotdescription&amp;quot:-1})
&gt;متد ()createIndex لیستی از گزینه ها را قبول می‌کند که در زیر آمده‌اند:همانطور که گفته شد Indexing در MongoDB بخش کوچکی از مجموعه داده‌ها را به شکل ساده‌ای برای پیمایش، ذخیره می‌کنند.امیدوارم از مطالب ذکر شده بهره کافی را برده باشید با ما همراه باشید تا در جلسه بعد، توابع جمعی در MongoDB را آموزش ببینید.The dropIndex() متدشما می توانید با استفاده از روش dropIndex() یک شاخص خاص را حذف کنید.سینتکسسینتکس متد DropIndex به شرح ذیل می باشد:&gt;db.COLLECTION_NAME.dropIndex({KEY:1})در اینجا کلید نام فایلی است که می خواهید ایندکس را روی آن ایجاد کنید و 1 برای ترتیب صعودی است. برای ایجاد ایندکس به ترتیب نزولی باید از -1 استفاده کنید.مثال:&gt; db.mycol.dropIndex({&amp;quottitle&amp;quot:1})
{
	&amp;quotok&amp;quot : 0,
	&amp;quoterrmsg&amp;quot : &amp;quotcan&#039;t find index with key: { title: 1.0 }&amp;quot,
	&amp;quotcode&amp;quot : 27,
	&amp;quotcodeName&amp;quot : &amp;quotIndexNotFound&amp;quot
}The dropIndexes() methodنحو اصلی متد DropIndexes() به صورت زیر است:&gt;db.COLLECTION_NAME.dropIndexes()مثال:فرض کنید ما 2 شاخص در مجموعه mycol نامگذاری شده مانند شکل زیر ایجاد کرده ایم:&gt; db.mycol.createIndex({&amp;quottitle&amp;quot:1,&amp;quotdescription&amp;quot:-1})مثال زیر ایندکس های ایجاد شده در بالا از mycol را حذف می کند:&gt;db.mycol.dropIndexes({&amp;quottitle&amp;quot:1,&amp;quotdescription&amp;quot:-1})
{ &amp;quotnIndexesWas&amp;quot : 2, &amp;quotok&amp;quot : 1 }
&gt;The getIndexes() methodاین متد توضیحات تمامی ایندکس موجود در یک کالکشن را نمایش می دهد:db.COLLECTION_NAME.getIndexes()مثالدر پایین ما دو تا ایندکس در کالکشن mycol به شرح ذیل ایجاد می کنیم :db.mycol.createIndex({&amp;quottitle&amp;quot:1,&amp;quotdescription&amp;quot:-1})از طریق دستور زیر می توانیم همه ایندکس موجود در کالکشن mycol را نمایش داد:&gt; db.mycol.getIndexes()
[
	{
		&amp;quotv&amp;quot : 2,
		&amp;quotkey&amp;quot : {
			&amp;quot_id&amp;quot : 1
		},
		&amp;quotname&amp;quot : &amp;quot_id_&amp;quot,
		&amp;quotns&amp;quot : &amp;quottest.mycol&amp;quot
	},
	{
		&amp;quotv&amp;quot : 2,
		&amp;quotkey&amp;quot : {
			&amp;quottitle&amp;quot : 1,
			&amp;quotdescription&amp;quot : -1
		},
		&amp;quotname&amp;quot : &amp;quottitle_1_description_-1&amp;quot,
		&amp;quotns&amp;quot : &amp;quottest.mycol&amp;quot
	}
]
&gt;MongoDB - Aggregationعملگرهای جمعی، رکوردهای اطلاعات را پردازش می‌کنند و نتیجه‌های محاسبه شده را برمی‌گردانند.در sql، دستور (*)count همراه Group by معادل یک تابع جمعی در MongoDB است.متد ()aggregateسینتکس پایه برای این متد به شکل زیر است :&gt;db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)مثال
در این مجموعه شما داده های زیر را دارید.{   _id: ObjectId(7df78ad8902c)
   title: &#039;MongoDB Overview&#039;, 
   description: &#039;MongoDB is no sql database&#039;,
   by_user: &#039;tutorials point&#039;,
   url: &#039;http://www.tutorialspoint.com&#039;,
   tags: [&#039;mongodb&#039;, &#039;database&#039;, &#039;NoSQL&#039;],
   likes: 100
},
{
   _id: ObjectId(7df78ad8902d)
   title: &#039;NoSQL Overview&#039;, 
   description: &#039;No sql database is very fast&#039;,
   by_user: &#039;tutorials point&#039;,
   url: &#039;http://www.tutorialspoint.com&#039;,
   tags: [&#039;mongodb&#039;, &#039;database&#039;, &#039;NoSQL&#039;],
   likes: 10
},
{
   _id: ObjectId(7df78ad8902e)
   title: &#039;Neo4j Overview&#039;, 
   description: &#039;Neo4j is no sql database&#039;,
   by_user: &#039;Neo4j&#039;,
   url: &#039;http://www.neo4j.com&#039;,
   tags: [&#039;neo4j&#039;, &#039;database&#039;, &#039;NoSQL&#039;],
   likes: 750
},
اکنون اگر بخواهید از مجموعه‌ی بالا لیستی از تعداد دوره‌های نوشته شده توسط هر کاربر را نمایش دهید و استخراج کنید، باید ار متد ()aggregate به صورت زیر استفاده کنید :&gt; db.mycol.aggregate([{$group : {_id : &amp;quot$by_user&amp;quot, num_tutorial : {$sum : 1}}}])
{
   &amp;quotresult&amp;quot : [
      {
         &amp;quot_id&amp;quot : &amp;quottutorials point&amp;quot,
         &amp;quotnum_tutorial&amp;quot : 2
      },
      {
         &amp;quot_id&amp;quot : &amp;quotNeo4j&amp;quot,
         &amp;quotnum_tutorial&amp;quot : 1
      }
   ],
   &amp;quotok&amp;quot : 1
}
&gt;معادل کوئری بالا در sql به این شکل خواهد بود: (*)select by_user, countدر مثال بالا، سندهای گروه بندی شده‌ توسط فیلد by_user را داریم و در هر اجرای by_user مقدار قبلی جمع کلی افزایش می‌یابد.در اینجا لیست عبارت‌های جمعی موجود، آمده است.مفهوم Pipeline در MongoDBدر Command shell یونیکس، خط لوله (Pipeline) به معنی امکان اجرای یک عملیات روی چندین ورودی و استفاده از خروجی بعنوان ورودی برای دستور بعدی و ادامه‌ی آن است. MongoDB نیز pipeline در MongoDB را در چارچوب توابع جمعی پشتیبانی می‌کند.یک مجموعه از مراحل وجود دارند که هرکدام از آنها یک مجموعه از اسناد را بعنوان ورودی می‌گیرند و یک مجموعه از سند را بعنوان نتیجه (یا نتیجه را بعنوان سند JSON در پایان خط لوله) ارائه می‌دهند. این عمل به نوبه خود می‌تواند برای مرحله بعد و یا مراحل بعدی، استفاده شود.مراحل ممکن در چارچوب توابع جمعی در زیر آمده اند:$project : برای انتخاب چندین فیلد از یک مجموعه استفاده می‌شود.$match : این یک عملگر فیلترگذاری است که می‌تواند میزان اسنادی را که بعنوان ورودی در مرحله بعد گرفته می‌شوند، کاهش دهد.$group : این همان تابع جمعی است که در بالا توضیح داده شد.$skip : توسط این عبارت، در یک لیست بدست آمده (نتیجه)، می‌توانید از لیست اسناد بصورت روبه جلو صرفنظر کنید.$limit : این عبارت تعداد اسناد را توسط عدد گرفته شده، از موقعیت فعلی برای نمایش محدود می‌کند.$unwind : این عبارت برای باز کردن (unwind) سندی که از آرایه‌ها بهره گیری می‌کند استفاده می‌شود. وقتی از آرایه استفاده می‌کنید، داده از نوع پیش پیوست (Pre-joined) است و با این نوع داده، این عمل برای داشتن سندهای اختصاصی نا تمام خواهد ماند. بنابراین با این مرحله می‌توانید میزان اسناد را برای مرحله بعد افزایش دهید.به طور کلی عملیات جمعی مقادیر چندین سند را باهم گروه بندی می‌کند و می‌تواند یک نوع از عملگرها را روی اطلاعات دسته بندی شده انجام دهد تا یک نتیجه‌ی واحد را برگرداند.MongoDB - Replicationتکثیر، افزونگی را فراهم می‌آورد و دسترسی پذیری داده‌ها را توسط کپی داده در چندین سرور مختلف افزایش می‌دهد.این کار، یک پایگاه داده را در مقابل از دسترس خارج شدن یک سرور مفرد، محافظت می‌کند.همچنین امکان بازیابی از خرابی سخت افزار و وقفه‌های سرویس را به کاربر می‌دهد.توسط کپی برداری از اطلاعات، می‌توانید یکی از آنها را برای بازیابی، گزارشگیری و پشتیبان گیری اختصاص دهید.چرا تکثیر؟برای ایمن نگه داری اطلاعاتدسترسی پذیری بالای اطلاعات (شبانه روزی)بازیابی اطلاعاتنیازی به از کار افتادن هنگام انجام عملیات نگه‌داری نداردمقایس پذیری خواندن داده‌ها (کپی برداری‌های اضافه برای عمل خواندن)کپی اطلاعات برای نرم افزارها شفاف و قابل دستیابی است.تکثیر در MongoDB چگونه عمل می‌کند ؟MongoDB عمل تکثیر را با استفاده از مجموعه کپی (Replica set) انجام می‌دهد. مجموعه کپی یک گروه از نمونه‌های mongodb هستند که مجموعه داده یا dataset مشابهی را میزبانی (Host) می‌کنند.در کپی داده، یک گره، گره اصلی است و تمام عملیات نوشتن را دریافت می‌کند. بقیه‌ی نمونه‌ها، عملیات را از گره اصلی، دریافت و اعمال می‌کنند.بنابراین آنها هم dataset مشابهی دارند. مجموعه‌ی کپی تنها می‌تواند یک گره‌ اصلی داشته باشد.یک مجموعه‌ی کپی، یک گروه از دویا چند گره است. (عموما حداقل ۳ گره نیاز است.)در یک مجموعه‌ی کپی، یک گره، گره اصلی است و بقیه گره‌ها گره‌های ثانویه هستند.همه‌ی داده‌ها از گره‌ی اصلی به گره‌های ثانویه تکثیر می‌شوند.هنگام انجام عملیات نگه داری یا ازدسترس خارج شدن سرور، گزینش برای گره اصلی و انتخاب گره اصلی جدید آغاز می‌شود.گره از کار افتاده، بعد از بازیابی دوباره، به مجموعه کپی ملحق می‌شود و بعنوان یک گره ثانویه کار می‌کند.در زیر یک نوع دیاگرام از تکثیر در MongoDB نشان داده شده است که در آن برنامه‌ی سمت کلاینت همیشه با گره‌ی اصلی در ارتباط است و گره‌ی اصلی، داده‌ها را گره‌های ثانویه تکثیر می‌کند.ویژگی‌های مجموعه‌ی کپییک کلاستر از N عدد گرههر گره‌ایی می‌تواند گره اصلی باشد .همه‌ی عملیات نوشتن بر روی گره اصلی انجام می‌شود .عمل ازدسترس خارج شدن سرور و جایگزین شدن یک گره بصورت اتوماتیکبازیابی بصورت اتوماتیکهمراهی و توافق در گزینش گره اصلیساختن یک مجموعه کپیدر اینجا می‌خواهیم یک نمونه از mongodb را به یک مجموعه‌ی کپی تبدیل کنیم. برای این کار مراحل زیر را انجام دهید:همه‌ی نمونه‌های در حال اجرای mongod را در سمت سرور، متوقف کنید.اکنون mongod سمت سرور را با سوئیچ –replSet راه اندازی کنید.سینتکس پایه –replSet به شکل زیر است:mongod --port &amp;quotPORT&amp;quot --dbpath &amp;quotYOUR_DB_DATA_PATH&amp;quot --replSet &amp;quotREPLICA_SET_INSTANCE_NAME&amp;quotmongod --port 27017 --dbpath &amp;quotD:\set up\mongodb\data&amp;quot --replSet rs0دستور فوق یک نمونه از mongod را با نام rs0، روی پورت ۲۷۰۱۷ راه اندازی می‌کند. اکنون command prompt را باز کنید و به این نمونه mongod متصل شوید.در سمت کلاینت، دستور ()rs.initiate را برای شروع کردن یک مجموعه‌ی کپی جدید صادر کنید.برای چک کردن تنظیمات مجموعه‌ی کپی، دستور ()rs.conf را صادر کنید. برای چک کردن وضعیت مجموعه کپی نیز دستور ()rs.status را صادر کنید.افزودن اعضا به مجموعه‌ی کپیبرای افرودن اعضا به مجموعه‌ی کپی، چند نمونه mongodb را در چندین کامپیوتر راه اندازی کنید.اکنون برنامه‌ی سمت کلاینت را اجرا و دستور ()rs.add را اجرا کنید.سینتکسسینتکس پایه دستور ()rs.add به شکل زیر است:&gt;rs.add(HOST_NAME:PORT)مثالفرض کنید نام نمونه‌ی mongodb شما mongod1.net و بر روی پورت ۲۷۰۱۷ در حال اجراست. برای افزودن این نمونه به مجموعه کپی، دستور () rs.add را در سمت کلاینت اجرا کنید.&gt;rs.add(&amp;quotmongod1.net:27017&amp;quot)
&gt;وجه کنید که فقط وقتی می‌توانید یک نمونه mongodb را برای مجموعه کپی اضافه کنید که به گره اصلی متصل باشید. برای چک کردن اینکه به گره اصلی متصل هستید، دستور ()db.isMaster را در سمت کلاینت صادر کنید.MongoDB - Shardingچرا Sharding؟در عمل تکثیر، همه‌ی نوشتن‌ها به سمت گره اصلی می‌ روند.پرس و جوهای حساس به تاخیر نیز به سمت گره اصلی می‌ روند.مجموعه کپی مفرد به ۱۲ گره محدود است.وقتی دیتاست خیلی بزرگ می‌شود، حافظه به اندازه کافی نمی‌تواند بزرگ شود.دیسک محلی به اندازه‌ی کافی بزرگ نیست.هزینه مقیاس پذیری عمودی بسیار بالاست.عملیات Sharding در MongoDBدیاگرام زیر نحوه Sharding در MongoDB را نشان می‌دهد:در دیاگرام بالا سه جز اصلی وجود دارند که در ادامه توضیح داده شده‌اند:Shards: Shard برای ذخیره داده استفاده می‌شود. آنها دسترس پذیری بالا و پایداری داده را فراهم می‌کنند.در محیط تولید هر Shard یک مجموعه کپی جداست.Config Servers: Config Server متا دیتای کلاستر را نگهداری می‌کند.این داده‌ها شامل اطلاعات نگاشت دیتاست کلاستر برای Shardهاست. مسیریاب کوئری (query router) از این متا دیتا برای نشان گذاری عملیات برای Shard‌های تعیین شده استفاده می‌کند. در محیط تولید Shard شده، کلاسترها دقیقا ۳ سرور تنظیمات دارند.Query Routers: مسیریاب کوئری‌ها بطور اساسی نمونه‌های mongos و واسط بین برنامه کلاینت هستند و عملیات را به Shard مناسب هدایت می‌کنند. مسیریاب کوئری عملیات را برای Shard، پردازش و نشان گذاری می‌کنند و نتیجه را برای کاربر برمی گردانند. یک Shard کلاستر شده می‌تواند شامل چندین مسیریاب کوئری (برای تقسیم بارگیری درخواست کلاینت) باشد. یک کلاینت می‌تواند درخواست هایش را یه یک مسیریاب کوئری ارسال کند. عموما یک Shard کلاستر شده چندین مسیریاب کوئری دارد.همانطور که اندازه‌ی داده در افزایش است، شاید تنها یک ماشین  برای ذخیره سازی داده‌ها کافی نباشد و یا نتواند کارآیی قابل قبولی را برای خواندن و نوشتن فراهم کند. Sharding این مشکل را با مقایس پذیری افقی حل نموده است. توسط Sharding، می‌توانید دستگاه‌های دیگری را برای پشتیبانی از داده‌های درحال رشد بیافزایید و عملیات خواندن و نوشتن را بیشتر پوشش دهید.MongoDB - Create Backupنحوه پشتیبان گیری در MongoDBبرای پشتیبان گیری از اطلاعات، از فایل جداگانه‌ی دیگری درشاخه Bin استفاده میکنیم که MongoDump نام دارد و یک فایل دامپ را ایجاد میکند.سینتکس پایه برای دستور mongodump به شرح زیر است :&gt;mongodumpمثالسرور Mongod خود را شروع کنید فرض کنید که سرور mongod شما در localhost و در پرت ۲۷۰۱۷ اجرا می شود، دستور prompt را باز کنید و به پوشه bin در نمونه mongodb خود بروید و دستور mongodump را تایپ کنید.اکنون فرض کنید مجموعه mycol دارای داده های زیر است.&gt;mongodumpفرمان به سرور در حال اجرا در ۱۲۷٫۰٫۰٫۱ و پورت ۲۷۰۱۷ متصل شده و تمام اطلاعات سرور را به دایرکتوری / bin / dump / متصل می کند.پس خروجی فرمان به شکل زیر است :در زیر لیستی از گزینه های موجود که می تواند با دستور mongodump مورد استفاده قرار گیرد آورده شده است بازگرداندن داده هابرای بازگرداندن اطلاعات پشتیبان از فرمان mongorestore MongoDB استفاده می شود.این دستور تمام داده ها را از دایرکتوری پشتیبان بازیابی می کند.سینتکس پایه برای دستور mongorestore به شکل زیر می باشد :&gt;mongorestoreنتیجه پشتیبان گیری از همه دیتابیس‌ها و همه قسمت‌ها به انضمام فایل‌ها در شاخه‌ای به اسم dump در پوشه Bin صورت میگیرد.آموزش پشتیبان گیری در MongoDB به اتمام رسید. در جلسه بعد توسعه در MongoDB  را آموزش خواهیم داد.با  ما همراه باشید.MongoDB - Deploymentبهترین روش شامل نمونه سازی از راه اندازی شما، انجام آزمایش بار، نظارت بر شاخص های کلیدی، و استفاده از آن اطلاعات برای تنظیمات بخش اصلی این رویکرد است که به طور کامل سیستم شما را نظارت می کند.این به شما کمک خواهد کرد که قبل از توسعه سیستم تولید خود را حفظ کنید و تعیین کنید که آیا باید ظرفیت را اضافه کنید. برای مثال، داشتن بینش در مورد استفاده از حافظه های احتمالی، می تواند باعث جلوگیری از ضربه زدن به قفل کردن نوشتن شود.برای نظارت بر محیط توسعه در مونگو ، MongoDB برخی از دستورات زیر را فراهم می کند.mongostatاین فرمان وضعیت تمام موارد مونگو را اجرا می کند و شمارنده ها را از عملیات پایگاه داده باز می کند.این شمارنده ها شامل درج ها، نمایش ها، به روز رسانی ها، حذف، و مکان نما هستند.همچنین این فرمان هنگام برخورد با  صفحهhitting، درصد قفل خود را نشان می دهد.این به این معنی است که حافظه شما هنگام اجرا کم شده،یا مشکل ظرفیت نوشتن و برخی از مشکلات عملکرد بوجود آمده است.برای اجرای دستور،روی نمونه ای از mongod خود شروع کنید.در خط فرمان دیگر، روی مسیر bin در نصب mongodb بروید و mongostat را تایپ کنید.D:\set up\mongodb\bin&gt;mongostatخروجی فرمان به شکل زیر می باشد :mongotopاین فرمان فعالیت های خواندن و نوشتن نمونه MongoDB را بر اساس مجموعه جمع آوری و گزارش می کند.به طور پیش فرض، mongotop اطلاعات را در هر ثانیه باز می گرداند، و شما می توانید آن را تغییر دهید.شما باید بررسی کنید که این فعالیت خواندن و نوشتن با هدف برنامه شما منطبق است یا خیر.برای اجرای دستور، نمونه ای از mongod خود را شروع کنید.سپس در خط فرمانی دیگری، به مسیر bin روی نصب mongodb بروید و  mongotop را وارد کنید.D:\set up\mongodb\bin&gt;mongotopخروجی فرمان به شکل زیر می باشد :برای تغییر دستور mongotop برای به حداقل رساندن اطلاعات، یک شماره خاص بعد از دستور mongotop مشخص کنید.D:\set up\mongodb\bin&gt;mongotop 30مثال بالا مقدار را هر ۳۰ ثانیه یکبار برمی گرداند.به غیر از ابزار MongoDB، ابزار ۱۰gen یک سرویس مانیتورینگ میزبانی رایگان، سرویس مدیریت (MongoDB MMS) را فراهم می کند، که یک داشبورد را ایجاد می کند و به شما یک معیار از کل خوشه شما را می دهدبا تشکر از مطالعه این مقاله ,مثل همیشه کنجکاو باشید!!!در دوره های آموزش تضمینی مجتمع فنی ارومیه که به صورت خصوصی و عمومی در دو شیوه حضوری و آنلاین برگزار می شود سرفصل های بسیار متنوع و کاربردی را بصورت پروژه محور آموزش داده می شود تا شخص کارآموز بتواند بلافاصله پس از اتمام این دوره در کمترین زمان ممکن وارد بازار کار شود.آموزش تخصص ماست با ما حرفه ای شویدجهت مشاوره با شماره 09149431772 در ارتباط باشید ... https://www.aparat.com/javadjahangiriniopdc/playlists </description>
                <category>جواد جهانگیری</category>
                <author>جواد جهانگیری</author>
                <pubDate>Sun, 17 Oct 2021 08:05:34 +0330</pubDate>
            </item>
            </channel>
</rss>