Skip to content

介紹一些 Model 與 Manager 的使用策略 #24

@uranusjr

Description

@uranusjr

Fat model and mangers, forms when suitable, thin views, trivial templates.

節錄一些 Gitter 對話


壞範例:

from django.db import models

class Restaurant(models.Model):
    is_fastfood = models.BooleanField()
    average_price = models.IntegerField()

# In view.
some_restaurants = Restaurant.objects.filter(
    is_fastfood=False, average_price__gte=100,
)

好範例:

from django.db import models

class RestaurantQuerySet(models.QuerySet):
    def some(self):
        return self.filter(is_fastfood=False, average_price__gte=100)


class Restaurant(models.Model):
    is_fastfood = models.BooleanField()
    average_price = models.IntegerField()
    objects = RestaurantQuerySet.as_manager()

# In view.
some_restaurants = Restaurant.objects.some()

最主要的好處其實是會讓你的 view 很好讀

找到一個好像還不錯的例子

有個 project 需要找到使用者在一個範圍內能看到的所有 remote 物件

# 一個頁面顯示一個 region
user = request.user
if not user.is_authenticated():
    remotes = Remotes.objects.none()
else:
    remotes = Remote.objects.filter(
        location__isnull=False,
        location__contained=region.boundary,
    )
    if not user.is_superuser:
        remotes = remotes.filter(owner_set__in=[user])

邏輯大概像這樣

我們把測試使用者權限的程式抽出來

class OwnableQuerySet(QuerySet):
    def get_viewable(self, user):
        # Exclude objects not owned by user unless the user is a superuser.
        if not user.is_authenticated():
            return self.none()
        elif user.is_superuser:
            return self.all()
        return self.filter(owner_set__in=[user])

然後把找 region 中 remotes 的程式抽出來

class Region(models.Model):
    # ...
    def get_visible_remotes(self, user):
        remotes = Remote.objects.filter(
            location__isnull=False,
            location__contained=self.boundary,
        )
        remotes = remotes.get_viewable(user=user)
        return remotes

最後在 view 裡就變成這樣:

# 一個頁面顯示一個 region
remotes = region.get_visible_remotes(user=request.user)

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions