Skip to content

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

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)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions