Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Movie Search
#1
I've finished the movie search script. Still a little ruff around the edges but, works. I had trouble placing text in the textbox so I went with using a frame in the textbox. That way I could kinda order the layout a little. I welcome any input. Remember it will take a few seconds to get the results as it does a few queries. My understanding of the imdb database may search through several pages to get the information.

# Do the imports
from imdb import Cinemagoer
import tkinter as tk
from tkinter import ttk
from urllib.request import urlopen
from PIL import ImageTk, Image
import io

class Data:
    '''
    The Data class retrieves all information from user input
    Searches person and movies returns all relevant information
    '''
    def __init__(self):
        self.action = Cinemagoer()

    def search_person(self, name):
        person = self.action.search_person(name.strip())[0]
        return person.get('name'), person.personID
    
    def get_person(self, id):
        person = self.action.get_person(id)
        jobs = [job for job in person.get('filmography').keys()]
        movies = [movie for movie in person['filmography'][jobs[0]]]
        return person.get('name'), movies
    
    def search_movies(self, title):
        return self.action.search_movie(title)
    
    def get_movie(self, movie_id):
        if movie_id:
         movie = self.action.get_movie(movie_id)
         return movie
    

class Window:
    '''
    Window class is for visual and has fields and buttons
    for the Controller class to use
    '''
    def __init__(self, parent):
        parent.columnconfigure(0, weight=1)
        parent.rowconfigure(0, weight=1)
        parent.minsize(800,600)
        parent['padx'] = 5
        parent['pady'] = 3
        parent['bg'] = '#c0c0c0'
        parent.title('Movie Search')
        
        container = tk.Frame(parent, bg='#333333')
        container.grid(column=0, row=0, sticky='news')
        container.grid_columnconfigure(0, weight=3)
        container.grid_rowconfigure(3, weight=3)

        header = tk.Label(container, text='Movie Search', fg='#ffffff', bg='#333333')
        header['font'] = 'tk.HEADER 28 bold'
        header.grid(column=0, row=0, sticky='new', padx=2, pady=2)

        self.msg = tk.Label(container, text='Messages: ', bg='#555555', fg='#FFFFFF', anchor='w', padx=10)
        self.msg['font'] = 'tk.MENU 13 normal'
        self.msg.grid(column=0, row=1, sticky='new', padx=2, pady=2)

        row1 = tk.Frame(container, bg='#555555')
        row1.grid(column=0, row=2, sticky='new', padx=2, pady=2)
        for i in range(5):
            weight = 4 if i == 3 else 3
            row1.grid_columnconfigure(i, weight=weight, uniform='cols')

        row2 = tk.Frame(container, bg='#555555')
        row2.grid(column=0, row=3, sticky='news', padx=2, pady=2)
        row2.grid_columnconfigure(0, weight=3, uniform='tree')
        row2.grid_columnconfigure(2, weight=3, uniform='tree')
        row2.grid_rowconfigure(0, weight=3)

        row3 = tk.Frame(container, bg='#555555')
        row3.grid(column=0, row=4, sticky='new', padx=2, pady=2)
        row3.grid_columnconfigure(0, weight=3)

        label = tk.Label(row1, text='Search by:', bg='#555555', fg='#ffffff')
        label['font'] = 'None 12 normal'
        label.grid(column=0, row=0, sticky='new', padx=2, pady=4)

        self.options = ['Actors/Actresses', 'Movie Title']
        self.picked = tk.StringVar()
        self.picked.set(self.options[0])
        
        self.searchby = tk.OptionMenu(row1, self.picked, *self.options)
        self.searchby['font'] = 'None 10 normal'
        self.searchby.grid(column=1, row=0, sticky='new', padx=2, pady=4)
        self.searchby.config(border=0)

        label = tk.Label(row1, text='Search For:', bg='#555555', fg='#ffffff')
        label['font'] = 'None 12 normal'
        label.grid(column=2, row=0, sticky='new', padx=2, pady=4)

        self.entry = tk.Entry(row1)
        self.entry['font'] = 'None 12 normal'
        self.entry.grid(column=3, row=0, sticky='new', padx=2, pady=4)

        self.button = tk.Button(row1, text='Search')
        self.button.grid(column=4, row=0, sticky='new', padx=2)

        columns = ('Title', 'Released', 'Movie ID')
        self.left_tree = ttk.Treeview(row2, columns=columns, show='headings', selectmode='browse')
        for column in columns:
            if column == columns[0]:
                self.left_tree.column(column, minwidth=0, width=300, stretch='yes')
            else:
                self.left_tree.column(column, minwidth=0, width=100)
            self.left_tree.heading(column, text=column.title())
        self.left_tree.grid(column=0, row=0, sticky='news', padx=2)

        left_scroll = tk.Scrollbar(row2, orient='vertical', command=self.left_tree.yview)
        self.left_tree.config(yscrollcommand=left_scroll.set)
        left_scroll.grid(column=1, row=0, sticky='ns', padx=2)

        self.textbox = tk.Text(row2)
        self.textbox.grid(column=2, row=0, sticky='news', padx=2)
        self.textbox.grid_columnconfigure(0, weight=3)

        textbox_scroll = tk.Scrollbar(row2, orient='vertical', command=self.textbox.yview)
        self.textbox.config(yscrollcommand=textbox_scroll.set)
        textbox_scroll.grid(column=3, row=0, sticky='ns', padx=2)

        sig = tk.Label(row3, text='my-python.org', bg='#333333', fg='#ffffff')
        sig['font'] = 'None 10 normal'
        sig.grid(column=0, row=0, sticky='new')


class Controller:
    '''
    Controller class handles all communications between the Data and Window class
    '''
    def __init__(self, data, window):
        self.data = data
        self.window = window
        self.images = []

        # Button Commands
        self.window.button['command'] = self.search

        #Dropdown command        
        self.window.picked.trace('w', self.clear)

        # Bind treeview
        self.window.left_tree.bind('<<TreeviewSelect>>', self.details)

    def search(self):
        '''
        Search method will lookup either actor or movie depending on the
        selection in the Window class. At the momment the search only works
        for finding actors and actresses
        '''
        # Clear the views
        self.window.left_tree.delete(*self.window.left_tree.get_children())
        self.window.textbox.delete('1.0', 'end')
        try:
            self.frame.destroy()
        except AttributeError:
            pass

        # Get the param for either person search or movie search
        picked = self.window.picked.get()
        
        # Get the name of the search. person or movie
        name = self.window.entry.get().strip()

        # Set alternation colors for the treeview
        self.window.left_tree.tag_configure('oddrow', background='#ccceee')
        self.window.left_tree.tag_configure('evenrow', background='white')

        # Clear the entry field
        self.window.entry.delete(0, 'end')

        # # Person was selected for search
        
        if picked == 'Actors/Actresses':
            self.window.msg['text'] = f'Messages: Search results for {name.title()}'
            
            # Call the Data class search_person method
            person = self.data.search_person(name.strip())
            

            # Get relevant data using the person[1] which is set to the person id
            data = self.data.get_person(person[1])
            
            # Create empty list to hold the data wanted
            movie_list = []

            # Loop through the data getting relevant information
            # Also checking that there is a year for the movie release
            # This helps in not getting any movies not yet released
            for movie in data[1]:
                if movie.get('year'):
                    movie_list.append((movie.get('title'), movie.get('year'), movie.movieID))
                elif movie.get('year') == None:
                    year = self.data.get_movie(movie.movieID).get('year')
                    if year:
                        movie_list.append((movie.get('title'), year, movie.movieID))
                    else:
                        pass
            
        else:
            movies = self.data.search_movies(name.strip())
            movie_list = []
            for movie in movies:

                if movie.get('year'):
                    movie_list.append((movie.get('title'), movie.get('year'), movie.movieID))
                elif movie.get('year') == None:
                    year = self.data.get_movie(movie.movieID).get('year')
                    if year:
                        movie_list.append((movie.get('title'), year, movie.movieID))
                else:
                    pass

        movie_list.sort(key=lambda year: year[1])
        # Loop through the movie_list and insert into the treeview with alternating colors
        for index, movie in enumerate(movie_list):
            if index % 2 == 0:
                self.window.left_tree.insert('', index, values=(movie[0], movie[1], movie[2]), tags=('oddrow',))
            else:
                self.window.left_tree.insert('', index, values=(movie[0], movie[1], movie[2]), tags=('evenrow',))

        
    def details(self, id):
        item = self.window.left_tree.focus()
        try:
            id = self.window.left_tree.item(item)['values'][2]
        except IndexError:
            pass
        try:
            self.frame.destroy()
        except AttributeError:
            pass

        try:
            details = self.data.get_movie(id)
            title = details.get('title')
            cast = details.get('cast')
            year = details.get('year')
            plot = details.get('plot outline')
            cover = details.get('cover')
            rating = details.get('rating')
            air_date = details.get('original air date')

            cast_list = [c.get('name') for c in cast]
            cast = ', '.join(cast_list)

            img_url = urlopen(cover).read()
            img = Image.open(io.BytesIO(img_url))
            image = ImageTk.PhotoImage(img)

            
            self.frame = tk.Frame(self.window.textbox,bg='white')
            self.frame.grid(column=0, row=0, sticky='news')
            self.frame.grid_columnconfigure(0, weight=3)

            label = tk.Label(self.frame, text=f'Title', anchor='w',bg='white')
            label['font'] = 'tk.HEADER 10 bold'
            label.grid(column=0,row=0,sticky='new',pady=8)
            label = tk.Label(self.frame, text=f'{title}', anchor='w',bg='white')
            label.grid(column=1,row=0,sticky='new',pady=8)
            
            label = tk.Label(self.frame, text=f'Year:', anchor='w',bg='white')
            label['font'] = 'tk.HEADER 10 bold'
            label.grid(column=0, row=1, sticky='new',pady=8)
            label = tk.Label(self.frame, text=f'{year}', anchor='w',bg='white')
            label.grid(column=1, row=1, sticky='new',pady=8)

            label = tk.Label(self.frame, text=f'Air Date:', anchor='w',bg='white')
            label['font'] = 'tk.HEADER 10 bold'
            label.grid(column=0, row=2, sticky='new',pady=8)
            label = tk.Label(self.frame, text=f'{air_date}', anchor='w',bg='white')
            label.grid(column=1, row=2, sticky='new',pady=8)

            label = tk.Label(self.frame, text=f'Cover Image:', image=image, compound='bottom',anchor='w',bg='white')
            label['font'] = 'tk.HEADER 10 bold'
            label.grid(column=0, row=3, columnspan=2, sticky='new',pady=8)
            
            label = tk.Label(self.frame, text=f'Rating:', anchor='w',bg='white')
            label['font'] = 'tk.HEADER 10 bold'
            label.grid(column=0, row=4, sticky='new',pady=8)
            label = tk.Label(self.frame, text=f'{rating}', anchor='w',bg='white')
            label.grid(column=1, row=4, sticky='new',pady=8)

            label = tk.Label(self.frame, text=f'Plot:', anchor='w', wraplength=800, justify='left',bg='white')
            label['font'] = 'tk.HEADER 10 bold'
            label.grid(column=0, row=5, sticky='new',pady=8)
            label = tk.Label(self.frame, text=f'{plot}', anchor='w', wraplength=800, justify='left',bg='white')
            label.grid(column=1, row=5, sticky='new',pady=8)

            label = tk.Label(self.frame, text=f'Cast:', anchor='w', wraplength=800, justify='left',bg='white')
            label['font'] = 'tk.HEADER 10 bold'
            label.grid(column=0, row=6, sticky='new',pady=8)
            label = tk.Label(self.frame, text=f'{cast}', anchor='w', wraplength=800, justify='left',bg='white')
            label.grid(column=1, row=6, sticky='new',pady=8)
            
            self.window.textbox.delete('1.0', tk.END)
            self.window.textbox.insert('end', self.frame)
            self.images.append(image)
        except TypeError:
            pass

    def clear(self, write, index, mode):
        # Clear the treevies
        self.window.left_tree.delete(*self.window.left_tree.get_children())
        self.window.textbox.delete('1.0', 'end')
        self.window.msg['text'] = 'Messages: '
        try:
            self.frame.destroy()
        except AttributeError:
            pass

if __name__ == '__main__':
    root = tk.Tk()
    img = urlopen('https://my-python.org/images/code-forum/light/light_on.png')
    data = img.read()
    image = tk.PhotoImage(data=data)
    root.wm_iconphoto(True, image)
    controller = Controller(Data(), Window(root))
    root.mainloop()

Attached Files

Thumbnail(s)
   
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply


Messages In This Thread
Movie Search - by menator01 - Sep-07-2023, 04:36 AM
RE: Movie Search - by menator01 - Sep-10-2023, 09:59 PM
RE: Movie Search - by menator01 - Sep-15-2023, 01:30 AM
RE: Movie Search - by gluke15 - Oct-30-2023, 03:13 PM
RE: Movie Search - by EdwardMatthew - Jan-24-2024, 12:29 PM

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020