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
RockandMetal. Rock songs ids is1,3,4,5,8,9and Metal songs ids is11,12. Result of your raw sql query for my example data is[{'id': 1}, {'id': 3}, {'id': 4}, {'id': 5}, {'id': 8}, {'id': 9}, {'id': 11}, {'id': 12}]The same can be achieved with these two queries.