Syntax | سینتکس – Telegram
📊 Raw Queries and Connection Proxy in Django

🔍 How to Get Raw Queries in ORM

در جنگو، اگر ویژگی .query یک QuerySet را چک کنیم، می‌توانیم پرس‌وجو SQL مربوطه را دریافت کنیم. به عنوان مثال:

from author import models
all_authors = models.Author.objects.filter(email__endswith='@gmail.com').values_list('name').query


خروجی:

SELECT "author_author"."name" FROM "author_author" WHERE "author_author"."email"::text LIKE '%@gmail.com'



⚠️ چالش!

در جستجوهای ORM جنگو، دستورهایی داریم که غیر از QuerySet هستند و استفاده از .query باعث ایجاد خطا می‌شود. به عنوان مثال:

from author import models
author_count = models.Author.objects.filter(email='a').count().queries


خطا:

Traceback (most recent call last):
File "<console>", line 1, in <module>
AttributeError: 'int' object has no attribute 'query'



🛠 راه‌حل با استفاده از Connection Proxy

برای حل این مشکل، از connection در django.db استفاده می‌کنیم:

from django.db import connection
from author import models

author_count = models.Author.objects.filter(email='a').count()
connection.queries[-1]


خروجی:

{'sql': 'SELECT COUNT(*) AS "__count" FROM "author_author" WHERE "author_author"."email" = \'a\'', 'time': '0.166'}



📌 توجه!

شی connection فقط زمانی نتیجه می‌دهد که سرور جنگو در حالت DEBUG=True در حال اجرا باشد!

📝 نوشتن Debug Queries برای درک Connection Proxy

from django.db import connection
from django.db import reset_queries

def database_debug(func):
def inner_func(*args, **kwargs):
reset_queries()
results = func(*args, **kwargs)
query_info = connection.queries
print(f'function_name: {func.__name__}')
print(f'query_count: {len(query_info)}')
queries = [f'{query["sql"]}\n' for query in query_info]
print(f'queries: \n{"".join(queries)}')
return results
return inner_func


📌 توجه! تابع reset_queries تمام پرس‌وجوهای ذخیره شده در connection را پاک می‌کند!

🔧 استفاده از کد:

@database_debug
def regular_query():
blogs = models.Blog.objects.all()
return [blog.author.name for blog in blogs]


خروجی:

function_name: regular_query
query_count: 4
queries:
SELECT "blog_blog"."id", "blog_blog"."noscript", "blog_blog"."content", "blog_blog"."author_id"



💡 توضیح کد:

با استفاده از دستور reset_queries تمام پرس‌وجوهای ذخیره شده در connection را حذف می‌کنیم تا فقط کوئری‌های خواسته شده دیباگ شوند. سپس کوئری‌های داخل inner_function که دکوراتور شده‌اند اجرا می‌شوند و شی connection حاوی لیست از پرس‌وجوها می‌شود. بعد از آن، تمام پرس‌وجوها را از connection.queries بازیابی می‌کنیم.


🔗 منبع : کتاب django in productions
👍7🔥4🥰1
Django Serializers: Related Fields in Serializer


وقتی با مدل‌های مرتبط در Django کار می‌کنیم، نمایش اطلاعات کامل آن‌ها در سریالایزرها می‌تواند چالش‌برانگیز باشد. خوشبختانه، Django REST Framework (DRF) ابزارهای قدرتمندی برای این کار در اختیار ما قرار می‌دهد.

سریالایزر DRF به‌طور پیش‌فرض برای فیلدهای مرتبط در هنگام سریال‌سازی داده‌ها از مقدار primary key استفاده می‌کند. به عنوان مثال:

class Author(models.Model):
name = models.CharField()
last_name = models.CharField()

class Blog(models.Model):
noscript = models.CharField()
author = models.ForeignKey(Author, on_delete=models.CASCADE)

class BlogSerializer(serializers.ModelSerializer):
class Meta:
model = Blog
fields = "__all__"


خروجی BlogSerializer به شکل زیر خواهد بود:

{
"noscript": "black python",
"author": 3
}


حالا اگر بخواهیم به جای PK، اطلاعات اضافی از Author نمایش دهیم، چند راه حل وجود دارد:

1. استفاده از depth:
با تنظیم پارامتر 1 = depth در Meta کلاس سریالایزر، می‌توانید مشخص کنید که تا چه عمقی از روابط مدل‌ها سریالایز شوند. این روش ساده و سریع است، اما کنترل کمتری بر روی داده‌های خروجی به شما می‌دهد.

class BlogSerializer(serializers.ModelSerializer):
class Meta:
model = Blog
depth = 1


خروجی BlogSerializer به شکل زیر خواهد بود:

{
"noscript": "python black",
"author": { "name": "amirhossein", "id": 1, "last_name": "some last name" }
}


2. استفاده از Nested Serializers:
با تعریف سریالایزرهای تو در تو، می‌توانید کنترل کاملی بر روی فیلدهایی که می‌خواهید از مدل‌های مرتبط نمایش دهید داشته باشید. این روش انعطاف‌پذیرتر است، اما نیاز به نوشتن کد بیشتری دارد , مثال:

class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
fields = ("name",)

class BlogSerializer(serializers.ModelSerializer):
author = AuthorSerializer()

class Meta:
model = Blog
fields = "__all__"


خروجی به شکل زیر خواهد بود:

{
"noscript": "black python",
"author": { "name": "amirhossein" }
}


مشکل N + 1 در هنگام استفاده از Depth یا Nested Serializer:
حتما باید در queryset خود از select_related یا prefetch_related استفاده کنید تا از بروز مشکل N + 1 جلوگیری کنید!

Django Serializers: Validators

1 : field level validators
برای اعتبار سنجی داده ها در سطح فیلد در drf باید از دستور زیر پیروی کنید:
class BlogSerializer(serializers.ModelSerializer):
....
def validate_<field name>(self, value): # validate_email
if vlaue in "_" :
serializers.ValidationError("some error")
return value

2 : object level validator

class BlogSerializer(serializers.ModelSerializer):
....
def validate(self, attrs):
if attrs.name == attrs.noscript :
serializers.ValidationError("name and noscript can not be same")
return value


Django Serializers: to_internal_value
متود to_internal_value در ModelSerializer قبل از اجرای اعتبارسنجی داده ها به داده های خام دسترسی دارد و میتوانید برای تغییر داده ها یا اضافه کردن داده ها قبل از اعتبارسنجی از اون استفاده کنید:
class BlogSerializer(serializers.ModelSerializer):
....
def to_internal_value(self, data):
data["user"] = self.context["user"] # افزودن شی user به data
return super().to_internal_value(data)

نکته:
اقا حتما موقع return از super().to_internal_value(data) استفاده کنید و return data استفاده نکنید ; چون اینطوری باعث میشه تمام validatorهای modelSerializer که از روی مدل شما بطور پیشفرض ساخته شده , غیرفعال بشن!

Django Serializers: to_representation

ما میتوانیم این رو ش را override کنیم تا قبل از داده های سریالی که نمونه سریالسازبر میگرداند،
دستکاری داده ها را انجام دهیم , مثال:
class BlogSerializer(serializers.ModelSerializer):
....
def to_representation(self, instance):
resp = super().to_representation(instance)
resp['noscript'] = resp['noscript'].upper()
return resp


برای اطلاعات بیشتر به کتاب :django in production مراجعه کنید.
👍82🔥1
نکات مهم اجرای جنگو با Gunicorn

توضیح درباره Gunicorn
نمیخوام توضیحات زیادی بدم حوصلتون سر بره پس همون سه خط معرفی که تو وب سایت gunicorn نوشته رو براتون یکم شفافش میکنم:
اسمش مخفف green unicorn هستش
جی یونیکورن یک http سرور هستش که از استاندارد WSGI(Web server gateway interface) برای اجرای برنامه های وب پایتون استفاده میکنه.
استاندارد WSGI برای این بوجود اومد تا هر فریم ورک وب پایتونی روش خودشو واسه ارتباط پیاده نکنه و همه از یه استاندارد مشخص استفاده کنن.

در ادامه میگه gunicorn برای unix هستش و برای سیستم عامل هایی مثل مک و لینوکس طراحی شده.

بعدش میگه که جی یونیکورن از مدل pre-fork worker استفاده میکنه حالا این به چه معنیه؟
جی یونیکورن کاری که میکنه اینه قبل اینکه شروع به پردازش درخواست ها کنه، میاد و به اندازه ای که تنظیم کردید worker ایجاد میکنه که هر worker درخواست هارو بطور مستقل پردازش میکنه.

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

قسمت آخرشم میگه light resource هستش و منابع کمی مصرف میکنه همچنین برای ترافیک بالا عملکرد خوبی داره.

خب جی یونیکورن این ادعا هارو میکنه اما بیاید با چند تا مثال شرایطی رو بررسی کنیم که شما به غلط دارید از جی یونیکورن استفاده میکنید:

مثال اول
gunicorn --chdir config config.wsgi:application -b 0.0.0.0:8000

اگه با این دستور جی یونیکورن رو اجرا کنید باید به این نکته دقت کنید بصورت پیشفرض براتون فقط یدونه worker میسازه که این اصلا خوب نیست. خود جی یونیکورن پیشنهاد میده حتی اگه یدونه core دارید 4 تا ورکر بسازید و یه فرمولی هم داده که میگه«تعداد هسته های سی پی یو رو ضربدر 2 به علاوه یک کنید»
همچنین به شما اطمینان داده همین تعداد ورکر هزاران ریکوئست رو میتونن پاسخ بدن پس تعداد ورکر هارو الکی زیادش نکنید.
البته به کیس شما هم بستگی داره.
دستور بهتر برای اجرا اینه تعداد ورکر هارو مشخص کنیم:
gunicorn --workers 5 --chdir config config.wsgi:application -b 0.0.0.0:8000


مثال دوم:
فرض کنید کاربر ها تو اپلیکیشن شما فایل هایی رو آپلود میکنن. شما پنج تا ورکر دارید.
وقتی پنج تا کاربر همزمان فایل آپلود کنن بنظرتون چه اتفاقی میوفته؟
پنج تا ورکر شما گیر یه io افتادن و مشغولن و درخواست های دیگه کاربرا انجام نمیشه. خب این وضعیتی نیست که باب میلیتون باشه!
برای حل این مشکل کافیه از gevent توی جی یونیکرون استفاده گنید؛
gunicorn --workers 1 -k gevent --chdir config config.wsgi:application -b 0.0.0.0:8000

با فلگ -k نوع کلاس ورکر رو مشخص میکنیم. حالا چرا از gevent استفاده میکنیم؟
کتابخونه gevent برای مدریریت همزمانی طراحی شده. میشه گفت یک نمونه lightweight thread هستش که این مدل موقع عملیات های IO سوئیچینگ انجام میده و در این صورت اگه به io خوردید براتون هندل میکنه.

کلی نکات دیگه هم قطعا هست که تو یه پست جا نمیشه
امیدوارم براتون مفید باشه

#python #django #gunicorn #gevent

@Syntax_fa
👍154🔥1🙏1
شب همگی سینتکسیا خوش باشه😉

بطور خیلی خلاصه اول ازتون میخوام که با دقت از این دو تا ویدیو فرانت اند وبسایت syntax دیدن کنید و انتخاب خودتون بهمون بگید که کدوم یکی از لحاظ تناسب و سایز ویجت ها و فونت ها به نسبت desktop بردیگری برتری داره؟

(جزئیات هر فرانت رو زیر ویدیو درج میکنم)
5👍2🔥1
This media is not supported in your browser
VIEW IN TELEGRAM
فرانت اند (۱)

توضیحات :
رفقا دیزاین سایز هر دو فرانت اند 1440 در 1024 هست ، اندازه desktop که فرانت اند نشون میده ۱۳۶۶ در ۷۳۸ هست .
اینجا برای اینکه آیتم ها ظاهر خودشون رو در هر نوع desktop حفظ کنه از scale کردن استفاده کردیم (بعضی جاها کل آیتم scale شده ، بعضی جاها برخی قسمت ها) .

طراحی فونت ها براساس متریال دیزاین هست و چون desktop ما از design size کوچیک تره ،برای اینکه ظاهر مینیمال و جذاب خودشو حفظ کنه از تمام فونت ها 2px کم کردیم و خروجی نهایی این شده
🔥72👍2
This media is not supported in your browser
VIEW IN TELEGRAM
فرانت اند (۲):

توضیحات :
Design size: 1440 x 1024
Desktop size : 1366 x 738

توی این دیزاین هم برخی آیتم هارو scale کردیم اما تفاوت قابل توجه در فونت ها و ویجت هایی که parent فونت ها هستن وجود داره .
ما تو این دیزاین size فونت هارو برای تمام desktop size ها ثابت قرار دادیم و مقدار ویجت والد رو بر اساس padding فونت ها بدست آوریم که خروجی شده این ویدیو
🔥7👍21
انتخاب شما کدومه ؟
Anonymous Poll
48%
فرانت ۱
52%
فرانت ۲
Syntax | سینتکس pinned «شب همگی سینتکسیا خوش باشه😉 بطور خیلی خلاصه اول ازتون میخوام که با دقت از این دو تا ویدیو فرانت اند وبسایت syntax دیدن کنید و انتخاب خودتون بهمون بگید که کدوم یکی از لحاظ تناسب و سایز ویجت ها و فونت ها به نسبت desktop بردیگری برتری داره؟ (جزئیات هر فرانت…»
⭐️ بنیاد دیسترو | حامی جهان اپن سورس

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

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

@DistroFDN
github.com/distrofdn/distrofdn

#open_source

@Syntax_fa
Please open Telegram to view this post
VIEW IN TELEGRAM
👍62🔥1
Audio
کتاب django in production رو دادم به notebook llm و یه پادکست ساخته برامون که این کتاب درمورد چیا صحبت میکنه و یه دید کلی میده نسبت به کتاب.


پ.ن: سرویس notebook llm خلاصه مقاله یا کتابی که بهش دادید رو مثل یه پاکست که دو نفر دارن درمورد اون مقاله صحبت میکنن درمیاره!

SOURCE

@Syntax_Fa
🔥12👍31
🔍 بررسی استراتژی جداسازی عملیات چک کردن وجود و بازیابی اطلاعات از دیتابیس

دو رویکرد اصلی در این زمینه در نظر داریم:

1️⃣ جداسازی مسئولیت‌ها:
در این روش، دو متد جداگانه داریم:
- check_user_exists(user_id)
- get_user_by_id(user_id)

مزایا:
رعایت Single responsibility(SRP)
خوانایی و وضوح بیشتر کد
امکان استفاده مجدد از هر متد به صورت مستقل

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

2️⃣ ترکیب عملیات در یک متد:
در این روش، یک متد واحد داریم:
- get_user(user_id)

مزایا:
کاهش تعداد کوئری‌های ارسالی به دیتابیس
بهبود کارایی

معایب:
احتمال نقض اصل Single responsibility
کاهش خوانایی و وضوح کد

🤔 حالا سوال این است: کدام رویکرد بهتر است؟

پاسخ: بستگی دارد!

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

3️⃣ رویکرد میانه:
در این روش، یک متد اصلی داریم که می‌تواند مبنای سایر عملیات باشد:

class UserService:
@staticmethod
def get_user(user_id: int) -> Optional[User]:
try:
return User.objects.get(id=user_id)
except User.DoesNotExist:
return None

@staticmethod
def check_user_exists(user_id: int) -> bool:
return UserService.get_user(user_id) is not None

@staticmethod
def get_user_or_raise(user_id: int) -> User:
user = UserService.get_user(user_id)
if user is None:
raise ObjectDoesNotExist(f"User with id {user_id} does not exist")
return user


این رویکرد مزایای هر دو روش را ترکیب می‌کند:
تنها یک کوئری به دیتابیس زده می‌شود
اصل مسئولیت تکی تا حد زیادی رعایت می‌شود
انعطاف‌پذیری بیشتری در استفاده داریم
کد خوانا و قابل نگهداری است

شما کدام رویکرد را ترجیح می‌دهید؟

@Syntax_fa
1👍9👎1🔥1
Forwarded from Normal Developer
This media is not supported in your browser
VIEW IN TELEGRAM
شرکت SpaceX در موفقیتی تاریخی، تونسته بوستر Super Heavy رو روی برجی که از اون پرتاب شده بود، روی دو بازوی مکانیکی این برج با دقت فوق العاده ای فرود بیاره!

@normal_developer
👍8🔥2
Linter & pylint

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

کاربردهای Linter


1. شناسایی خطاهای سینتکسی:
لینتر می‌توانند خطاهای سینتکسی را قبل از اجرای کد شناسایی کنند.

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

3. کاهش باگ‌ها:
با شناسایی مسائل بالقوه، به کاهش تعداد باگ‌ها کمک می‌کنند.

4. یکنواختی کد:
با اطمینان از رعایت استانداردهای یکسان در سراسر پروژه، یکنواختی کد را حفظ می‌کنند.

معرفی Pylint

پای لینت یک ابزار Linter برای زبان Python است که به تحلیل کد Python می‌پردازد تا مشکلات مختلفی مانند خطاهای سینتکسی عدم رعایت استانداردهای PEP 8 و مسائل منطقی را شناسایی کند.

ویژگی‌های Pylint


- شناسایی خطاهای نحوی و منطقی:
Pylint می‌تواند خطاهای نحوی و منطقی را در کد شناسایی کند.

- پیشنهاد برای بهبود کد:
با ارائه پیشنهادهایی برای بهبود کد، توسعه‌دهندگان را در نوشتن کدهای تمیزتر و بهینه‌تر یاری می‌دهد.

- پشتیبانی از استانداردهای PEP 8:
با بررسی کد نسبت به استانداردهای PEP 8، به رعایت بهترین شیوه‌های کدنویسی کمک می‌کند.

- گزارش‌دهی جامع:
گزارش‌های کاملی از مشکلات موجود در کد ارائه می‌دهد که شامل امتیازدهی به کیفیت کد نیز می‌باشد.

مثال نحوه استفاده از pylint:
pip install pylint

بعد از نصب کردن با دستور
pylint .

تمامی کد های پروژه را بررسی می کند.
خیلی مواقع نیاز است که لینتر ها و تنظیماتشان را تغییر بدهیم. برای اینکار دستور زیر را میزنیم تا فایل کانفیگ لینتر ساخته شود:
pylint --generate-rcfile > .pylintrc

در فایل .pylintrc می توانید بر حسب نیاز خودتان برخی از لینتر هارا غیر فعال کنید یا تنظیماتشان را تغییر دهید.

نحوه استفاده کاربردی از لینتر:
میتوانید در github workflow از لینتر استفاده کنید و اگر مشکلی شناسایی شد اکشن با خطا مواجه شود. همچنین می توانید از ابزار pre commit استفاده کنید و لینتر را تعریف کنید تا هر زمانی که کامیت جدیدی زده میشود بررسی کند اگر خطایی وجود دارد جلوی کامیت را بگیرد.

#linter #pylint #python

@Syntax_fa
1🔥6👍4
Docker in Docker (DinD)

به اجرای Docker در داخل یک کانتینر اشاره دارد.

یک مثال کاربردی اش پایپ‌لاین CI/CD است:

- در برخی مواقع ممکن است پروژه ما برای اجرا و تست نیاز به یک سری backing service ها مثل redis و ... داشته باشد. در این صورت ترفندی که می زنیم را می توان اینطور بیان کرد که داخل کانتینر، کانتینر های مورد نیاز پروژه مان را آپ می کنیم.

مثال:
ci.yml
name: CI

on:
pull_request:
types: [opened, edited, reopened, synchronize, ready_for_review]
branches: [main]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements/test.txt

- name: dockerUp
run: sudo make docker-test-up

- name: Test
run: make test

- name: dockerDown
run: sudo make docker-test-down


و داخل فایل Makefile:
.PHONY: test

ROOT=$(realpath $(dir $(lastword $(MAKEFILE_LIST))))

test:
python manage.py test

docker-test-up:
docker compose -f $(ROOT)/docker-compose-test.yml up -d

docker-test-down:
docker compose -f $(ROOT)/docker-compose-test.yml down


چالش DinD در موارد بیشتر

1. امنیت:
- اجرای Docker در Docker می‌تواند خطرات امنیتی به همراه داشته باشد، زیرا کانتینر داخلی به Docker Host دسترسی دارد.

2. پیچیدگی شبکه:
- کانفیگ شبکه می‌تواند پیچیده شود، به ویژه اگر نیاز به ارتباط بین کانتینرهای داخلی و خارجی باشد.

3. عملکرد:
- ممکن است عملکرد ضعیف‌تری نسبت به اجرای Docker به صورت مستقیم روی سرور داشته باشد.

نحوه استفاده

برای استفاده از Docker in Docker، می‌توانید از ایمیجی مانند docker:dind استفاده کنید. یک نمونه ساده از اجرای DinD به صورت زیر است:

docker run --privileged --name dind-container -d docker:dind


استفاده از فلگ --privileged ضروری است تا کانتینر به منابع سیستم دسترسی کامل داشته باشد.

جایگزین‌ها

در بسیاری از موارد، استفاده از روش‌های جایگزین مانند Docker خارج از کانتینر یا استفاده از ابزارهایی مانند Kubernetes می‌تواند مشکلات مربوط به DinD را حل کند و امنیت بیشتری فراهم کند.

#DinD

@Syntax_fa
👍5🔥2💋1
🤣20😁1
Forwarded from Normal Developer
ممکنه شما هم برای هاستینگ سایت یا اپلیکیشنتون از لیارا (liara.ir) استفاده کنید.
حدودا از سال ۱۴۰۰ سرویسای دم دستی که لازم داشتم رو میبردم روی لیارا یا حداقل نسخه اولیه رو اونجا ران میکردم.
سایت شخصی خودم رو هم اونجا ران کردم چون میخواستم از قابلیت های آماده ش استفاده کنم و زیاد روی تنظیم زیرساخت زمان نذارم و بیشتر روی توسعه تمرکز کنم.
ولی تو چند ماه اخیر واقعا با لیارا مشکل پیدا کردم و برام نه صرفه داره که ازش استفاده کنم و نه کیفیتشون مثل قبل خوبه.
تو ماه های جدید برای هر قابلیتی دارن یه قیمتی میدن.
فرض کنید یه سایت ساده با مثلا پایتون با کمترین منابع ران کنید روی لیارا. ببینیم چقد در میاد:

هزینه PaaS ماهانه: ۹۹ هزار تومن (512 مگابایت رم - ۰.۵ هسته پردازنده- ۵ گیگ حافظه)
هزینه بسته امکاناتی: ۷۴ هزار تومن (برنزی)
هزینه دیتابیس پستگرس: ۹۹ هزار تومن (۵۱۲ مگابایت رم - ۰.۵ هسته پردازنده - ۵ گیگ فضای ذخیره سازی)

جمعا: ۲۷۲ هزار تومن ماهانه معادل حدود 4.5 دلار در ماه
حالا اگه شما بخواید یه سرور مجازی بگیرید از یه دیتاسنتر خوب مث هتزنر یا OVH هم حدود ۵ دلار در ماه هزینه داره.
ولی منابعی که مثلا هتزنر دراختیارتون قرار میده میشه ۴ گیگابایت رم، ۲ هسته پردازنده، ۴۰ گیگ فضا!
به اضافه اینکه کیفیت زیرساختی خیلی بهتری داره.
در ادامه بنچمارک GTMetrics از یه سرویس نسبتا پرتصویر و عکس که روی هتزنر دارم و سایت شخصی خودم که هیچی نداره رو میذارم.

@Normal_Developer
👍10👎1
Forwarded from Normal Developer
میبینید که یه سایت ساده لیارا بنچ C گرفته
در مقابل یه سایت که تصویر هم زیاد داره روی هتزنر بنچ A گرفته!

@Normal_Developer
👍13👎2😱1
اگه کانفیگ های v2ray که پول هم دادی براش کار نمیکنه این پست رو چک کن:

https://news.1rj.ru/str/normal_developer/25

@syntax_fa
👍4👎1
یه شخصی تو لینکدین این پست رو گذاشته که قراره با هم بررسیش کنیم:
چرا نباید از Signals ها در جنگو استفاده کنیم؟

اگر تجربه کار با Django را داشته باشید، احتمالاً با Signals آشنا هستید. سیگنال‌ها به شما این امکان را می‌دهند که بعد از رخ دادن یک رویداد خاص، مانند ذخیره یا حذف یک شی، کدی را اجرا کنید. اما آیا همیشه بهترین انتخاب هستند؟ بیایید با هم بررسی کنیم.

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

چرا نباید از سیگنال‌ها استفاده کنیم؟
با وجود کاربردهای سیگنال‌ها، استفاده از آن‌ها معایب خودشون رو هم دارن. یکی از مشکلات اساسی سیگنال‌ها این است که پیچیدگی و عدم پیش‌بینی‌پذیری را افزایش میدن. کدهایی که به‌وسیله سیگنال اجرا می‌شوند، ممکن است در جریان اصلی کد ما نباشند و ما به‌راحتی متوجه نشیم که چه زمانی و چرا آن‌ها فراخوانی می‌شوند. این موضوع نه تنها کار دیباگ کردن رو سخت میکنه، بلکه ممکنه رفتار ناخواسته‌ای هم که ازش انتظار نداریم رو هم داشته باشه.

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

به‌عنوان مثال، فرض کنید شما در حال توسعه کدی هستید که تعداد فروش یک نوع تاپینگ پیتزا را هنگام ایجاد پیتزای جدید به‌روزرسانی می‌کند. اگر از سیگنال استفاده کنید، ممکن است در مواردی که از متدهای bulk مانند bulk_create یا .update() استفاده می‌کنید، این سیگنال فراخوانی نشود و این به داده‌های ناهماهنگ منجر شود.

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

چه چیزی می‌تواند جایگزین باشد؟
به جای استفاده از سیگنال‌ها، یکی از راهکارهای بهتر استفاده از متدهای مدل مثل save() هست. زمانی که بیزینس لاجیک خود را درون متد save() مدل قرار می‌دهید، همه چیز شفاف‌تر و قابل پیش‌بینی‌تر خواهد بود. به این ترتیب، کد جلو چشم شما قرار دارد و نیازی نیست نگران اجرا شدن یا نشدن سیگنال‌ها باشید. این کار باعث می‌شود کد تمیزتر و خواناتر باشد و همچنین به‌راحتی قابل تست و نگهداری شود.

برای مثال، می‌توانید یک متد در مدل خود تعریف کنید که منطق به‌روزرسانی را مدیریت کند و سپس این متد را در متد save() فراخوانی کنید. این روش نه تنها ساختار کد شما را ساده‌تر می‌کند، بلکه به توسعه‌دهندگان آینده هم کمک می‌کند تا به‌راحتی جریان کد را دنبال کنند.
————————————-

نظر من راجب این پست:
استفاده از سیگنال ها تو برخی شرایط بنظرم خیلیم مفید هستش.

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

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

اینطوری سرویس ها نسبت به هم decouple تر شدن و دیگه یوزر کاری نداره زمانی که یوزری جدیدی ساخته شد، بقیه سرویس ها چیکار کنن، فقط سیگنالو ارسال میکنه هر کی علاقه مند بود دریافتش میکنه.

الگوی observer:
سیگنال ها درواقع پیاده سازی الگوی observer هستن که برای ارتباط بین اجزای مخنلف سیستم خیلی مفیده.

فقط چند تا نکته باقی میمونه اینکه از سیگنال ها هوشمندانه استفاده کنیم، تو استفاده ازشون زیاده روی نکنیم و حتما داکیومنت کنیم تا باعث سردرگمی نشه

#django #Signals

@Syntax_fa
👍5🔥3
📱 زندگی برنامه‌نویس‌ها قبل و بعد از چت‌بات‌های هوش مصنوعی:

قبل:
- گوگل: بهترین دوست
- Stack Overflow: خونه دوم
- کپی-پیست: مهارت اصلی

بعد:
- چت‌جی‌پی‌تی: رفیق فابریک
- پرامپت مهندسی: تخصص جدید
- هوش مصنوعی: همکار جدید

دنیای برنامه‌نویسی قبل از عصر هوش مصنوعی


برای نسل جدید برنامه‌نویسان که در عصر هوش مصنوعی و چت‌بات‌ها رشد کرده‌اند، تصور دنیای برنامه‌نویسی بدون این ابزارها شاید سخت باشد. اما واقعیت این است که تا همین چند سال پیش، برنامه‌نویسان با چالش‌های متفاوتی روبرو بودند.

جستجو: هنر اصلی برنامه‌نویسی


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

Stack Overflow: ناجی برنامه‌نویسان


سایت Stack Overflow نقش حیاتی در زندگی برنامه‌نویسان داشت. بسیاری از مشکلات با جستجو در این سایت و خواندن پاسخ‌های دیگران حل می‌شد. البته پیدا کردن پاسخ مناسب در میان انبوه نظرات، خود چالشی بزرگ بود.(هنوزم ناجی برنامه نویساس)

دیباگ: کابوس شبانه


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

#fun

@Syntax_fa
😁9👍6