یک توسعه‌دهنده

یک توسعه دهنده که بیشتر از توسعه،‌ فیلم می‌بینه و کتاب می‌خونه :)

نکته‌های جنگویی - کش کردن - قسمت دوم

دوشنبه, ۳ شهریور ۱۳۹۹، ۰۱:۳۲ ب.ظ

در قسمت قبلی پایه‌ی سری مطالب نکات جنگویی رو آماده کردم. و در این مطلب و مطالب بعدی نکته‌هایی که ممکنه بدردمون بخوره رو با هم یاد میگیریم.

کش کردن انواع مختلفی داره که هدف این مطلب، کش کردن با memcache هستش. برای استفاده از memcache باید روی سیستم خودتون نصبش کنید. بسته به سیستم‌عاملی که دارید memcache رو نصب کنید یا می‌تونید از داکر برای نصبش استفاده کنید.

نکته: تو یه پست جمع و جور پروژه‌ی جنگویی خودمون‌و داکری می‌کنیم تا خرکیف شیم.

حالا اگر لینوکس دارید با وارد کردن خط زیر می‌تونید memcache رو نصب کنید:

sudo apt install memcached

بعد هم نیاز به یه کتاب‌خونه memcache دارم که نصب می‌کنم:

pip3 install django-memcached

حالا تنظیمات memcache رو به A/settings.py اضافه می‌کنم:

# Cache
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': '127.0.0.1:11211',
    }
}

انواع کش کردن:

  • The per-site cache

  • The per-view cache

  • Template fragment caching

  • The low-level cache API

که در ادامه با هر کدوم از موارد بالا آشنا میشیم.


The per-site cache

در این روش،‌ کل پروژه کش میشه. با تغییر دادن MIDDLEWARE در A/settings.py :

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.cache.UpdateCacheMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.cache.FetchFromCacheMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

من ۷۳۸ داستان کوتاه رو وارد دیتابیسم کردم. و بدون اینکه کش انجام بدم، خوندن اطلاعات و هربار نشون دادنش چند ثانیه‌ای طول میکشه. اما با کش فقط دفعه‌ی اول چند ثانیه‌ای طول میکشه و دفعات بعدی به‌جای اینکه اطلاعات رو مستقیم از دیتابیس دیسک بخونه، اطلاعات رو از حافظه رم میخونه که سرعت خیلی بالاست.

 

The per-view cache

اگر میخواید که فقط بخشی از وب‌سایت رو کش کنید و کش کردن کل وب‌سایت نیاز ندارید، در stories/views.py:

from django.views.decorators.cache import cache_page

و دیکوریتور cache_page رو به شکل زیر استفاده می‌کنیم:

@cache_page(5 * 60)
def stories_list(request):
	context = {}

	stories = Story.objects.filter(status=True)

	context['stories'] = stories

	return render(request, 'stories/index.html', context)

که 5 * 60 نشون دهنده‌ی مدت زمان 5 دقیقه‌ای کش کردن هست.

 

روش دیگه اینه که کش کردن رو در stories/urls.py انجام بدیم که باز هم باید cache_page رو وارد کنیم و بعد:

from django.views.decorators.cache import cache_page

app_name = 'stories'

urlpatterns = [
	path('', (cache_page(5 * 60))(views.stories_list), name='stories_list'),
]

به این ترتیب کش کردن ما به‌جای views در urls انجام میشه. شخصا خودم از views کش میکنم. تمیزتره :).

 

 

Template fragment caching

همونطور که اسمش پیداست کش کردن در templateها انجام میشه. مثلا:

{% load cache %}
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>لیست داستان‌ها</title>
</head>

{% cache 300 content  %}
<body style="direction: rtl; text-align: justify">

	<h1>فهرست داستان‌ها</h1>
	<hr>
	{% for story in stories %}
		<h3><a href="{% url 'stories:stories_detail' story.slug %}">{{ story.title }}</a></h3>
		<small>{{ story.created|timesince }}</small><span>{{ story.user }}</span>
	{% endfor %}


</body>

{% endcache %}
</html>

اول کش رو لود کردم. و بعد اون ناحیه‌ای که میخوام کش شه رو داخل تگ کش content میذارم. ۳۰۰ (ثانیه) مدت زمان کش هست.

 

 

The low-level cache API

در روش آخر به‌صورت دستی اطلاعاتی که میخوایم رو وارد کش میکنیم. اول cache رو وارد می‌کنم:

from django.core.cache import cache

بعد از اون من میخوام که هر بار که داستانی باز میشه، اون داستان وارد کش شه و دفعات بعدی داستان مستقیما از دیتابیس خونده نشه. برای همین میام این کد زیر رو مینویسم:

@cache_page(5 * 60)
def stories_detail(request, slug):

	cache_key = f'story-{slug}'
	cache_time = 5 * 60

	story = cache.get(cache_key)

	if not story:
		story = get_object_or_404(Story, slug=slug, status=True)
	cache.set(cache_key, story, cache_time)

	return render(request, 'stories/detail.html', {'story': story})

یک کلید براساس slug درست می‌کنم و براساس این کلید کش رو میگیرم یا میسازم.

 

 

سعی کردم به‌صورت خلاصه و به‌دور از زیاده‌گویی یه سیستم کش ساده رو تو جنگو بنویسم. اگر نظری حرفی حدیثی هست خوشحال میشم با من در میون بذارید. 

 

پایان./

نظرات (۳)

سلام

خسته نباشید - ممنون از توضحات عالی

2تا  سوال داشتم

در روش template fragment caching  یا حتی روش های دیگه ، 

اگر اون زمانی که بهش دادیم ، تموم شه چه اتفاقی میفته ؟ دیگه از رو کش نمیخونه؟

سوال دوم : اگر قبل از اتمم اون زمان می یه تغییری دایدم ، بر فرض به به دسته بندی های سایت یه مورد اضافه کردیم  ؟ چه اتفاقی میفتهه ؟

پاسخ:
سلام. سلامت باشید.
۱. نه دیگه از کش خارج میشه؛ یک‌بار دیگه اطلاعات رو میخونه و وارد کش میکنه
۲. قبل از تموم شدن زمان، تغییرات رو نمی‌بینید و وقتی اطلاعات رو مجددا خوند، تغییرات رو می‌بینید.

درود بر شما

خیلی خوب بود. استفاده کردیم

پاسخ:
سلام به شما. خوشحالم که مفید بوده براتون :).
  • علیرضا آهنی
  • جنگو خیلی سخت به نظر میرسه ادم میترسه .

    پاسخ:
    فقط در ظاهر سخت به‌نظر میرسه. خیلی آسونه
    ارسال نظر آزاد است، اما اگر قبلا در بیان ثبت نام کرده اید می توانید ابتدا وارد شوید.
    شما میتوانید از این تگهای html استفاده کنید:
    <b> یا <strong>، <em> یا <i>، <u>، <strike> یا <s>، <sup>، <sub>، <blockquote>، <code>، <pre>، <hr>، <br>، <p>، <a href="" title="">، <span style="">، <div align="">
    تجدید کد امنیتی

    تمام حقوق مادی و معنوی این وبلاگ متعلق به وبلاگ سرزمین برنامه نویسی بوده و هر گونه کپی بردای بدون ذکر منبع غیرمجاز و از نظر ما حرام است