'django call related model queryset like rails activerecord merge scope
Say we have two models Account and Profile:
class Profile < ApplicationRecord
belongs_to :account
scope :age_upper, ->(age) { where("age > ?", age) }
end
class Account < ApplicationRecord
has_one :profile
end
Then we can have a query on Account model in Rails like this:
>>> Account.joins(:profile).merge(Profile.age_upper(18))
But with 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
My question is can we query from Account using filter age_upper of Profile instead of rewrite another one for Account like below
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)()
Solution 1:[1]
In Rails, you can't use a scope of one model to query another (at least with ActiveRecord). And even if you would find the way to do this that's probably not the best way to accomplish this.
If you don't want to write scopes or other shared logic again you can use concerns like that:
# app/models/concerns/shared_scopes.rb
module SharedScopes
extend ActiveSupport::Concern
included do
scope :age_upper, ->(age) { where("age > ?", age) }
end
end
And then include this concern in all model where you need this behavior:
# 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
Solution 2:[2]
you can write like below.
Account.objects.filter(profile_set__id__in=Profile.objects.age_upper(18).only('id'))
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Oleh Feilo |
| Solution 2 | takashi |
