<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های MrYazdan</title>
        <link>https://virgool.io/feed/@mryazdan</link>
        <description></description>
        <language>fa</language>
        <pubDate>2026-06-16 14:04:37</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/2710477/avatar/RCX5NN.jpg?height=120&amp;width=120</url>
            <title>MrYazdan</title>
            <link>https://virgool.io/@mryazdan</link>
        </image>

                    <item>
                <title>ارث بری مدل ها در جنگو - قسمت دوم ?</title>
                <link>https://virgool.io/@mryazdan/%D8%A7%D8%B1%D8%AB-%D8%A8%D8%B1%DB%8C-%D9%85%D8%AF%D9%84-%D9%87%D8%A7-%D8%AF%D8%B1-%D8%AC%D9%86%DA%AF%D9%88-%D9%82%D8%B3%D9%85%D8%AA-%D8%AF%D9%88%D9%85-n4xaxptuytvm</link>
                <description>Djnago Model Inheritanceتمام سند های متنشر شده در ویرگول ، در مخزن عمومی خود در گیتهاب وجود دارند (اول اونجا منتشر میشه ? ) : https://github.com/code-barg/daily-django-tips-fa جلسه قبل تر : ارث بری مدل ها در جنگو - قسمت اولبه نام خدا ، سلام سلام ?️ اومدیم با قسمت دوم ارث بری در مدل های فریمورک محبوب جنگو ، در قسمت قبل از مدل های انتزاعی و ارث بری ازشون گفتیم حالا بریم سراغ نوع دوم ارث بری ها که به پراکسی (proxy) معروفه بپردازیم ?مانند قبل ، بریم تعریف این نوع از مدل رو از خود جنگو ببینیم ❓Sometimes, however, you only want to change the Python behavior of a model – perhaps to change the default manager, or add a new method.This is what proxy model inheritance is for: creating a proxy for the original model. You can create, delete and update instances of the proxy model and all the data will be saved as if you were using the original (non-proxied) model. The difference is that you can change things like the default model ordering or the default manager in the proxy, without having to alter the original.همانطور که میبینید ، جنگو داره بهمون میگه: گاهی وقت ها شما میخواهید فقط رفتار پایتونی مدلتان متفاوت باشند یا به زبان آدمیزاد ، ممکنه وقت هایی بشه که برای یک جدول ما بصورت های متفاوتی قصد دریافت یا ارسال داده رو داشته باشیم ، اینجاست proxy مدل ها بکمکمون میان. ?به مثال زیر توجه کنید :from django.db import models
from django.utils import timezone


class Product(models.Model):
    title = models.CharField(max_length=100)
    created = models.DateTimeField(auto_now_add=True)
    
    
class OrderedProduct(Product):
    class Meta:
        proxy = True
        ordering = [&#039;created&#039;]

    def created_delta(self):
        return timezone.now() - self.createdخوب که بهش نگاه کنیم میبینیم هیچی نیست ! ?خب ما یک مدل Product داریم که تونستیم با ارث بری ازش یک مدل رفتاری (proxy) ازش بسازیم ، این مدل جدید با نام OrderedProduct نه ماهیت دیتابیسی داره (یعنی داخل دیتابیس چنین جدولی نیست) و نه اجازه این رو داره که تغییر دیتابیسی در مدل اصلی ایجاد کنه !سوال : پس فایدش چیه ؟ (به چه دردی میخوره):❓در پاسخ به این سوال میشه اینطور گفت که این مدل ها ، زمانی که شما قصد فیلتر کردن داده های اصلی (Product) را بصورت سطحی داشته باشید یا نسبت به خاصیتی (مثلا اگر این محصول تخفیف داشت !) متد هایی نیاز داشته باشید عملا بیفایده است و میتوان راهکار های ساده تری استفاده کرد ، ولی اگر مقصودتان فقط بصورت سطحی و کلی نباشد ، قصد جداسازی به همراه استفاده از الگو های بهینه سازی کوئری ها یا مثلا استفاده از Caching بطور جزئی و حرفه ای تر را داشته باشید استفاده از مدل های پراکسی شده بسیار عالی است !نتیجه :اول) ارث بری بصورت پراکسی مدل امکان رفتار پایتونیک بهتر و مقیاس پذیر تر را به ما میدهد. ✅دوم) در این نوع ارث بری ، ما نمیتوانیم تغییری در باطن یا ساختار اصلی مدل ایجاد کنیم. ❎مثال عملی و باحال از جلسه امروز (اهل دلاش اینجاشو دوست دارن ?)فایل ‍‍models.py‍ ما اینشکلیه :from django.db import models
from django.contrib.auth.models import Group, Permission, User


class SecurityFilter(models.Model):
    &amp;quot&amp;quot&amp;quot
    Security filter for a permission and a group by filter conditions.
    The filter conditions are evaluated in the context of the user.

    For example, if the filter conditions are &amp;quotuser.is_staff == True&amp;quot,
    then the filter is applied only if the user is staff.
    &amp;quot&amp;quot&amp;quot
    filter_conditions = models.TextField(verbose_name=&#039;filter conditions&#039;)
    group = models.ForeignKey(to=Group, related_name=&#039;filters&#039;, on_delete=models.CASCADE)
    permission = models.ForeignKey(to=Permission, related_name=&#039;filters&#039;, on_delete=models.CASCADE)

    def __unicode__(self):
        return &amp;quot%s for %s&amp;quot % (self.permission, self.group)


class SecurityUserManager(models.Manager):
    &amp;quot&amp;quot&amp;quot
    Manager for User model.

    This manager provides a method to get a queryset of available security filters
    &amp;quot&amp;quot&amp;quot

    @staticmethod
    def _get_filters(user, permission):
        &amp;quot&amp;quot&amp;quot
        Get security filters for a user and a permission.

        :param user: auth.models.User instance
        :param permission: auth.models.Permission instance
        :return: list of SecurityFilter instances
        &amp;quot&amp;quot&amp;quot
        return SecurityFilter.objects.filter(permission=permission, group__in=user.groups.all())

    @staticmethod
    def _build_query(filters):
        &amp;quot&amp;quot&amp;quot
        Build a query from a list of security filters.

        :param filters: list of SecurityFilter instances
        :return: a query object
        &amp;quot&amp;quot&amp;quot
        if not filters:
            return None

        query = models.Q()
        for conditions_set in (f.filter_conditions for f in filters):
            query |= models.Q(**eval&#40;conditions_set&#41;)

        return query

    def available(self, user, permission):
        &amp;quot&amp;quot&amp;quot
        Get a queryset of available security filters for a user and a permission.

        :param user: auth.models.User instance
        :param permission: auth.models.Permission instance
        :return: queryset of SecurityFilter instances
        &amp;quot&amp;quot&amp;quot
        filters = self._get_filters(user=user, permission=permission)
        query = self._build_query(filters)

        queryset = self.get_queryset()
        if query is None:
            return queryset.none()
        else:
            return queryset.filter(query)


class UserProxy(User):
    &amp;quot&amp;quot&amp;quot
    Proxy class for User model.
    &amp;quot&amp;quot&amp;quot
    objects = SecurityUserManager()

    class Meta:
        proxy = Trueچقدر ساده و پر استفاده ولی باحال ?برای تست و استفادش هم خب این هم فایل tests.py ما میتونه راهنمای کاملتون باشه :from django.test import TestCase
from django.contrib.auth.models import User, Permission, Group
from django.contrib.contenttypes.models import ContentType

from .models import SecurityFilter, UserProxy


class SecurityFilterTestCase(TestCase):
    def setUp(self):
        self.joker = User.objects.create_user(username=&#039;joker&#039;)
        self.victim_1 = User.objects.create_user(username=&#039;victim_1&#039;)
        self.victim_2 = User.objects.create_user(username=&#039;victim_2&#039;)
        self.batman = User.objects.create_user(username=&#039;batman&#039;)

        self.villains = Group.objects.create(name=&#039;villains&#039;)
        self.villains.user_set.add(self.joker)

        self.kill_and_rob = Permission.objects.create(
            name=&#039;kill and rob&#039;,
            codename=&#039;kill_and_rob&#039;,
            content_type=ContentType.objects.get(app_label=&#039;auth&#039;, model=&#039;user&#039;)
        )

        SecurityFilter.objects.create(
            filter_conditions=&amp;quot{&#039;username__startswith&#039;: &#039;victim&#039;}&amp;quot,
            permission=self.kill_and_rob,
            group=self.villains,
        )

    def test_basic_filtering(self):
        condition_string = SecurityFilter.objects.get().filter_conditions
        filter_query = eval&#40;condition_string&#41;

        users = User.objects.filter(**filter_query)
        victims = User.objects.filter(pk__in=[self.victim_1.pk, self.victim_2.pk])

        self.assertEqual(set(users), set(victims))

    def test_security_manager(self):
        users = UserProxy.objects.available(user=self.joker, permission=self.kill_and_rob)
        victims = User.objects.filter(pk__in=[self.victim_1.pk, self.victim_2.pk])

        self.assertEqual(set(users.values_list(&#039;pk&#039;, flat=True)), set(victims.values_list(&#039;pk&#039;, flat=True)))

    def test_security_manager_two_filters(self):
        SecurityFilter.objects.create(
            filter_conditions=&amp;quot{&#039;username&#039;: &#039;batman&#039;}&amp;quot,
            permission=self.kill_and_rob,
            group=self.villains,
        )

        users = UserProxy.objects.available(user=self.joker, permission=self.kill_and_rob)
        victims = User.objects.filter(pk__in=[self.victim_1.pk, self.victim_2.pk, self.batman.pk])

        self.assertEqual(set(users.values_list(&#039;pk&#039;, flat=True)), set(victims.values_list(&#039;pk&#039;, flat=True)))

    def test_security_manager_two_groups(self):
        archvillains = Group.objects.create(name=&#039;archvillains&#039;)
        archvillains.user_set.add(self.joker)

        SecurityFilter.objects.create(
            filter_conditions=&amp;quot{&#039;username&#039;: &#039;batman&#039;}&amp;quot,
            permission=self.kill_and_rob,
            group=archvillains,
        )

        users = UserProxy.objects.available(user=self.joker, permission=self.kill_and_rob)
        victims = User.objects.filter(pk__in=[self.victim_1.pk, self.victim_2.pk, self.batman.pk])

        self.assertEqual(set(users.values_list(&#039;pk&#039;, flat=True)), set(victims.values_list(&#039;pk&#039;, flat=True)))

    def test_security_manager_two_perms(self):
        make_joke = Permission.objects.create(
            name=&#039;make joke&#039;,
            codename=&#039;make_joke&#039;,
            content_type=ContentType.objects.get(app_label=&#039;auth&#039;, model=&#039;user&#039;)
        )
        SecurityFilter.objects.create(
            filter_conditions=&amp;quot{&#039;username&#039;: &#039;batman&#039;}&amp;quot,
            permission=make_joke,
            group=self.villains,
        )

        users = UserProxy.objects.available(user=self.joker, permission=make_joke)
        victims = User.objects.filter(pk__in=[self.batman.pk])

        self.assertEqual(set(users.values_list(&#039;pk&#039;, flat=True)), set(victims.values_list(&#039;pk&#039;, flat=True)))

    def test_security_manager_no_perms(self):
        SecurityFilter.objects.all().delete()

        users = UserProxy.objects.available(user=self.joker, permission=self.kill_and_rob)

        self.assertEqual(set(users.values_list(&#039;pk&#039;, flat=True)), set())موفق و پیروز باشید . ❤️</description>
                <category>MrYazdan</category>
                <author>MrYazdan</author>
                <pubDate>Sat, 15 Jul 2023 13:00:19 +0330</pubDate>
            </item>
                    <item>
                <title>ارث بری مدل ها در جنگو - قسمت اول ?</title>
                <link>https://virgool.io/@mryazdan/%D8%A7%D8%B1%D8%AB-%D8%A8%D8%B1%DB%8C-%D9%85%D8%AF%D9%84-%D9%87%D8%A7-%D8%AF%D8%B1-%D8%AC%D9%86%DA%AF%D9%88-%D9%82%D8%B3%D9%85%D8%AA-%D8%A7%D9%88%D9%84-mb4y6fr6fx37</link>
                <description>Django model inheritanceتمام سند های متنشر شده در ویرگول ، در مخزن عمومی خود در گیتهاب موجود هستند : https://github.com/code-barg/daily-django-tips-fa سلام ?️ حال و احوالتون خوش، قراره امروز بریم سراغ ارث بری در مدل های جنگو و یه سری از نکات رو ازش یاد بگیریم، خب از اینجا شروع میکنیم:A model is the single, definitive source of information about your data. It contains the essential fields and behaviors of the data you’re storing. Generally, each model maps to a single database table.مدل دقیقا خود جنگو اینطور تعریفش میکنه : یک مدل منبع انفرادی و قطعی اطلاعات در مورد داده های شما است. مدل ها شامل فیلدها و رفتارهای ضروری داده هایی است که ذخیره می کنید. به طور کلی، هر مدل به یک جدول پایگاه داده میباشد !و حالا ORM جنگو یه لطفی در حق ما داشته و به ما قابلیت های جالبی در ارث بری مدل ها داده که امروز میخواهیم باهم در موردش بدونیم.ORM stands for Object Relational Mapping. Django allows us to add, delete, modify and query objects, using an API called ORM. Django provides a default admin interface that is required to perform operations like create, read, update and delete on the model directly.بله ، orm هم طبق توضیح مخفف Object Relational Mapping است. جنگو به ما این امکان را می دهد که با استفاده از یک API به نام ORM، اشیاء را اضافه، حذف، اصلاح و پرس و جو کنیم. جنگو یک رابط مدیریت پیش‌فرض ارائه می‌کند که برای انجام مستقیم عملیاتی مانند ایجاد، خواندن، به‌روزرسانی و حذف روی مدل لازم است.انواع ارث بری در مدل هاوقتی صحبت از ارث بری در مدل های جنگو میشه در اصل یعنی قراره کلاسی از یک یا چند کلاس دیگر که همه از django.db.models.Model ارث برده اند، ارث بری کند ! چه شیر تو شیری شد ! سخت ترین کار دنیا، توضیح مفهومی کدارث بری انتزاعی (abstract)به مثال زیر توجه کنید :class TimeStampedModel(models.Model):
    created_at = models.DateTimeField(auto_add_now=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        abstract = True


class Post(TimeStampedModel):
    title = models.CharField(max_length=128)
    ...


class Product(TimeStampedModel):
    name = models.CharField(max_length=128)
    ...ما اگر n کلاس دیگر مثل Product هم داشته باشیم ، باز هم میتونیم براحتی از کلاس انتزاعی خودمون بنام TimeStampedModel استفاده کنیمخب حالا این عملیات چه نتیجه ای داره ؟ قبل از هر چیز به نکته ای که داره در این کد دقت کنید : ‍‍‍class ...:
    ...
	
    class Meta:
        abstract = True
...برای ساخت Mixin مدل ها که در حقیقت بصورت انتزاعی هستند باید این قاعده را رعایت کنیم .خب حالا تعریفش کنیم :‌ مدل های انتزاعی مدل هایی هستند کهاصلا موجودیتی در دیتابیس به تنهایی ندارند (جدول TimeStampedModel نداریم )زمانی مفید هستند که می‌خواهید برخی از اطلاعات رایج را در تعدادی مدل دیگر قرار دهید.وقتی به عنوان یک کلاس پایه برای مدل‌های دیگر استفاده می‌شود، فیلدهای آن به کلاس فرزند اضافه می‌شود.بریم برای یک مثال عملی و جالب :from django.db import models  
  
  
class TimeStampedModel(models.Model):  
	&amp;quot&amp;quot&amp;quot  
	TimeStampedModel  
	  
	An abstract base class model that provides self-managed &amp;quotcreated&amp;quot and  
	&amp;quotupdated&amp;quot fields.  
	&amp;quot&amp;quot&amp;quot  
	created = models.DateTimeField(auto_now_add=True)  
	updated = models.DateTimeField(auto_now=True)  
	  
	class Meta:  
		abstract = True  
		get_latest_by = &#039;created&#039; # default to get latest by created  
		ordering = [&#039;-created&#039;] # default to order by created descending  
  
  
class LogicalDeleteModel(models.Model):  
	&amp;quot&amp;quot&amp;quot  
	LogicalDeleteModel  
	  
	An abstract base class model that provides an &amp;quotis_deleted&amp;quot field.  
	&amp;quot&amp;quot&amp;quot  
	is_deleted = models.BooleanField(default=False)  
	  
	class Meta:  
		abstract = True  
  
  
class LogicalActiveModel(models.Model):  
	&amp;quot&amp;quot&amp;quot  
	LogicalActiveModel  
	  
	An abstract base class model that provides an &amp;quotis_active&amp;quot field.  
	&amp;quot&amp;quot&amp;quot  
	is_active = models.BooleanField(default=True)  
	  
	class Meta:  
		abstract = True  
  
  
class Product(LogicalActiveModel, LogicalDeleteModel, TimeStampedModel):  
	&amp;quot&amp;quot&amp;quot  
	Product model  
	  
	A product that can be purchased.  
	&amp;quot&amp;quot&amp;quot  
	name = models.CharField(max_length=128)  
	description = models.TextField()  
	price = models.DecimalField(max_digits=10, decimal_places=2)  
	quantity = models.IntegerField()  
	  
	def __str__(self):  
		return self.nameما در این مثال ۴ مدل را پیاده سازی کرده ایم هر سه مدل اول در حقیقت BaseModel یا مدل های انتزاعی هستند، و مدل های دیگر که اینجا ما فقط از مدل Product استفاده کردیم مدل هایی هستند که از قابلیت های مدل های انتزاعی بهره می ببرند.به فایل migrations این مدل ها دقت کنید‌:from django.db import migrations, models  
  
class Migration(migrations.Migration):  
	initial = True  
	operations = [  
		migrations.CreateModel(  
			name=&#039;Product&#039;,  
			fields=[  
				(&#039;id&#039;, models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name=&#039;ID&#039;)),  
				(&#039;created&#039;, models.DateTimeField(auto_now_add=True)),  
				(&#039;updated&#039;, models.DateTimeField(auto_now=True)),  
				(&#039;is_deleted&#039;, models.BooleanField(default=False)),  
				(&#039;is_active&#039;, models.BooleanField(default=True)),  
				(&#039;name&#039;, models.CharField(max_length=128)),  
				(&#039;description&#039;, models.TextField()),  
				(&#039;price&#039;, models.DecimalField(decimal_places=2, max_digits=10)),  
				(&#039;quantity&#039;, models.IntegerField()),  
			],  
			options={  
				&#039;abstract&#039;: False,  
			},  
		),  
	]متوجه شدید ؟ هیچ یک از مدل های abstract ما اصلا موجودیتی در دیتابیس ما ندارد ! ولی تمام خصوصیات هر یک از آن مدل ها روی مدل Product وجود دارد و در حقیقت ما از قواعد کد نویسی تمیز به همراه دسترسی و نظم بالا بهره برده ایم.نکته قابل توجه هم آنجاست که تمام متد (method) و پراپرتی (property) های کلاس های خود را دارند.خسته نباشید ?پینوشت ها:سطح این سند عمومی و آسان است ، پس در قسمت های بعدی سعی میکنیم ذره ذره سطح را ارتقا بدهیم.از دو abstract base class های مهم اینجا برای مثال در حد نمایش رو نمایی شده ، LogicalActive و LogicalDelete دو مدل انتزاعی پر استفاده و کارآمد هستند که بزودی برای هر کدوم جلسه ی مفصلی داریم.</description>
                <category>MrYazdan</category>
                <author>MrYazdan</author>
                <pubDate>Sat, 15 Jul 2023 12:32:33 +0330</pubDate>
            </item>
            </channel>
</rss>