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

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

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

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

توییتر رو در نظر بگیرید. یک کاربر ممکنه ۵۰ هزار توییت داشته باشه، اگر برای هر بار رفرش کردن Profile که حاوی توییت‌های کاربره، یک کوئری برای دریافت اطلاعات به سرور زده شه، بار خیلی خیلی زیادی به سرور وارد میشه.

راهکاری که در این مواقع استفاده میشه، کش کردن اطلاعات هست. مطلب کامل این موضوع در داکیومنت جنگو. برای این مطلب من یک پروژه‌ی آزمایشی را ساختم که برای نکته‌های دیگر جنگویی از همین استفاده خواهم کرد.

 

برای شروع یک دایرکتوری با اسم story ساختم:

mkdir story

وارد دایرکتوری story میشم و یک virtualenv درست میکنم:

cd story
➜  story python3 -m virtualenv -p python3 .venv

بعد از ساختن virtualenv، محیط مجازی رو فعال میکنم:

➜  story source ./.venv/bin/activate

جنگو رو نصب میکنم:

(.venv) ➜  story pip3 instal django 

و بعد از نصب جنگو، پروژه‌ی خودم که اسمش A هست رو میسازم:

(.venv) ➜  story django-admin startproject A

یک app به اسم stories درست میکنم:

(.venv) ➜  A ./manage.py startapp stories

حالا این app رو به INSTALLED_APPS اضافه میکنم:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # My Django apps
    'stories.apps.StoriesConfig',
]

حالا به stories/models.py میرم و مدل اپ رو میسازم که مدل من همچین چیزی هست:

from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse


class Story(models.Model):
	user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='user_stories')
	title = models.CharField(max_length=100)
	slug = models.SlugField(max_length=100, unique=True)
	body = models.TextField()
	created = models.DateTimeField(auto_now_add=True)
	updated = models.DateTimeField(auto_now=True)
	status = models.BooleanField(default=True)


	class Meta:
		verbose_name_plural = 'stories'
		ordering = ('-created', )
		
	def __str__(self):
		return self.title

حالا مدلی که ساختم رو migrate میکنم:

(.venv) ➜  A ./manage.py makemigrations
(.venv) ➜  A ./manage.py migrate

حالا در stories/views.py دو view که برای نمایش لیست داستان‌ها و نمایش یک داستان براساس slug می‌نویسم:

def stories_list(request):
	context = {}

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

	context['stories'] = stories

	return render(request, 'stories/index.html', context)
def stories_detail(request, slug):

	story = get_object_or_404(Story, slug=slug, status=True)

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

بعد از ساخت viewها دو فایل html برای نمایش اطلاعات میسازم.

stories/templates
└── stories
    ├── detail.html
    └── index.html

کدهای index.html:

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


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

</html>

کدهای detail.html:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>{{ story.title }}</title>
</head>
<body style="direction: rtl; text-align: justify">

	<h1>مطالعه داستان</h1><a href="{% url 'stories:stories_list' %}">خانه</a>
	<hr>
	<h3>{{ story.title }}</h3>
	<small>{{ story.created|timesince }}</small> | <span>{{ story.user }}</span>
	<hr>
	<p>{{ story.body|safe }}</p>


</body>
</html>

نکته: قاعدتا باید یه base.html بسازم و فایل‌های htmlی رو از اون extend کنم ولی در این سری مطالب هدف ما طراحی ظاهر نیست.

حالا میرم سراغ stories/urls.py (که باید ایجاد شه):

from django.urls import path
from . import views


app_name = 'stories'

urlpatterns = [
	path('', views.stories_list, name='stories_list'),
	path('<slug:slug>/', views.stories_detail, name='stories_detail'),
]

برای تنظیم urlهای اپ داستان به سراغ A/urls.py میرم و urlهای اپ خودم رو بهش معرفی میکنم:

from django.contrib import admin
from django.urls import path, include


urlpatterns = [
    path('admin/', admin.site.urls),

    # My apps urls
    path('', include('stories.urls')),
]

تا اینجا یه پروژه‌ی جنگویی ساختیم، که یه اپ برای نوشتن داستان هم داره. حالا باید یه کاربر ادمین بسازیم و پروژه رو اجرا کنیم:

(.venv) ➜  A ./manage.py createsuperuser
Username: admin
Email address: 
Password: 
Password (again): 
The password is too similar to the username.
This password is too short. It must contain at least 8 characters.
This password is too common.
Bypass password validation and create user anyway? [y/N]: y
Superuser created successfully.

نام کاربری admin و رمزعبور admin رو انتخاب کردم. و پروژه رو اجرا می‌کنم:

(.venv) ➜  A ./manage.py runserver      
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
August 23, 2020 - 03:07:12
Django version 3.1, using settings 'A.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

در مرورگر به آدرس:

http://localhost:8000/admin/

که بریم و بعد از وارد کردن اطلاعات کاربر ادمین، وارد پنل ادمین میشیم. اما من هنوز اپ stories رو به پنل ادمین اضافه نکردم. که به stories/admin.py میرم و این کار رو انجام میدم:

from django.contrib import admin
from .models import Story


@admin.register(Story)
class StoryAdmin(admin.ModelAdmin):
	list_display = ('user', 'title', 'slug', 'created', 'status')
	list_filter = ('user', 'created')
	search_fields = ('title', 'body')
	raw_id_fields = ('user', )

اگر حالا دوباره صفحه‌ی پنل ادمین رو رفرش کنم، میبینم که اپ استوری به پنل ادمین اضافه شده.

 

میخواستم تمام مطالب کش کرن رو داخل یه پست بنویسم، اما تصمیم گرفتم که تبدیل به دو بخشش کنم که بخش اول ساخت یه پروژه‌ی جنگو هست و برای بقیه‌ی مطالب جنگویی از همین پروژه استفاده کنم و لینک به همین صفحه بدم. قسمت دوم کش کردن که موضوع اصلی بحث ما هم هست رو به‌زودی مینویسم.

اگر خطا و مشکلی هم در مطلب دیدید زیر پست بهم اطلاع بدید.

 

پایان قسمت اول./

نظرات (۰)

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

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