Where clause on m2m field #266
-
Is it possible to create a where clause for searching within m2m fields? example class User(Table):
id = Integer(primary_key=True)
invited = M2M(LazyTableReference("InvitedUser", module_path=__name__))
attended = M2M(LazyTableReference("AttendedUser", module_path=__name__))
liked_songs = M2M(LazyTableReference("LikedSongs", module_path=__name__))
liked_playlists = M2M(LazyTableReference("LikedPlaylists", module_path=__name__))
liked_rooms = M2M(LazyTableReference("LikedRooms", module_path=__name__))
liked_genres = M2M(LazyTableReference("LikedGenres", module_path=__name__))
class Song(Table):
class Players(str, Enum):
audio = 'a'
apple = 'p'
spotify = 's'
youtube = 'y'
soundcloud = 's'
input = 'i'
id = Serial(primary_key=True)
track_id = Varchar(length=150, index=True, required=True)
name = Varchar(max_length=150, index=True, required=True)
created = Timestamptz(default=TimestamptzNow())
artist = Varchar(max_length=150, null=True)
album = Varchar(max_length=150, null=True)
metadata = JSONB(default={})
genres = M2M(LazyTableReference("Song2Genre", module_path=__name__))
logo = Varchar(max_length=150, null=True)
duration = Float(default=0.0, help_text='seconds')
player = Varchar(max_length=1, choices=Players, required=True)
uploaded_by = ForeignKey(references=User, on_delete=OnDelete.cascade)
playlists = M2M(LazyTableReference("Song2Play", module_path=__name__))
liked = M2M(LazyTableReference("LikedSongs", module_path=__name__))
same_songs = M2M(LazyTableReference("SameSongs", module_path=__name__)) I want to get all songs genres, that user liked user = await User.objects().get(User.id == user_id)
users_genres = await User.select(User.genres(Genre.id)).where(User.id == user_id)
user_genres = users_genres[0]
songs_of_genres = await Song.select(Song.id).where(Song.genres.is_in(user_genres))
# or
songs_of_genres = await Song.objects().where(Song.genres.is_in(user_genres)) now this just return AttributeError: 'M2M' object has no attribute 'is_in' Is it the only way now - download of songs and then manually check genres for each song? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 4 replies
-
As far as I know, this is not possible. If I understood your request correctly, you need to make two queries because is_in needs a list (as written in the docs). I think something like this will give the correct results (sorry if I didn't understand your request) # songs that the user liked
users_songs = (
await User.select(User.liked_songs(Song.id, as_list=True))
.where(User.id == 1)
.first()
)
# songs genres, that user liked
genres_per_user_songs = await Song.select(
Song.genres(Genre.name, as_list=True)
).where(Song.id.is_in(users_songs["liked_songs"]))
print([i["genres"] for i in genres_per_user_songs]) |
Beta Was this translation helpful? Give feedback.
On my example data user liked genres is
Rock
andMetal
. Rock songs ids is1,3,4,5,8,9
and Metal songs ids is11,12
. Result of your raw sql query for my example data isThe same can be achieved with these two queries.