Django呼叫相关的模型QuerySet,例如Rails ActivereCord合并范围



说我们有两个模型帐户和个人资料:

class Profile < ApplicationRecord
    belongs_to :account
    scope :age_upper, ->(age) { where("age > ?", age) }
end
class Account < ApplicationRecord
    has_one :profile
end

然后,我们可以在这样的轨道上对帐户模型进行查询:

>>> Account.joins(:profile).merge(Profile.age_upper(18))

但与django:

class ProfileQuerySet(models.QuertSet):
    def age_upper(age):
        return self.filter(age__gt=age)
class Profile(models.Model):
    account = models.ForiegnKey('Account', on_delete=models.CASCADE)
    objects = models.Manager.from_queryset(ProfileQuerySet)()

class Account(models.Model):
    pass

我的问题是,我们可以使用配置文件的过滤器age_upper从帐户查询,而不是重写另一个帐户,例如以下

class AccountQuerySet(models.QuertSet):
    def age_upper(age):
        return self.filter(profile__age__gt=age)
class Account(models.Model):
    objects = models.Manager.from_queryset(AccountQuerySet)()

在导轨中,您不能使用一个模型的范围来查询另一个模型(至少使用ActivereCord)。即使您会找到这样做的方法,这可能不是完成此操作的最佳方法。

如果您不想再次编写范围或其他共享逻辑,则可以使用此类问题:

# app/models/concerns/shared_scopes.rb
module SharedScopes
  extend ActiveSupport::Concern
  included do
    scope :age_upper, ->(age) { where("age > ?", age) }
  end
end

,然后将这种关注点包括在您需要此行为的所有模型中:

# app/models/profile.rb
class Profile < ApplicationRecord
  include SharedScopes
  belongs_to :account
end
# app/models/account.rb
class Account < ApplicationRecord
  include SharedScopes
  has_one :profile
end

您可以像下面的书面写作。

Account.objects.filter(profile_set__id__in=Profile.objects.age_upper(18).only('id'))

相关内容

最新更新