Overview
After hours of trial and error and more than a little foul language, I have managed to create a tkinter form that retrieves the products from the TechStore mongo database and lists them in a combo box, and that allows a user to choose one of them and then write a new review, which is then written to the database. There is much more to do, but this is good beginning for now.
Here is a list of the Mongo and python tutorials so far
- First steps with Mongo
- Mongo Database Two
- Mongo three beginning python
- More Pymongo inserts
- Python Objects Data Classes
Creating the Window
In keeping with using an object oriented approach, I created a class called Window that inherits from Frame.
def __init__(self, master=None): Frame.__init__(self, master) self.master = master self.init_window()
All the self and master stuff takes some getting used to and part of what made all this more difficult that it should have been. The init_Window is a method that initializes all the windows controls.
The first thing I do is a Label to prompt the user to choose a product from the drop down list.
# creating a label instance self.prompt = Label(self, text="Choose a product to Review") # placing the lable on the window self.prompt.place(x=10, y=0)
To get the products, I initialize the ProductManagment class and call two methods: populateProducts() and getProducts().The method populateProducts() is an addition since the blog on the data classes. It is there to make sure the array of products is populated. The whole code is available on the Github link at the end of the blog. The method getProducts() returns a cursor or array of product strings which I can use for the values argument of the ComboBox control.
#calling the product management class #to get the products pm = ProductManagement.ProductManagement() #making sure the product list is populated pm.populateProducts() products=pm.getProducts() #creating the Combobox and populating it with products self.productsCombo=ttk.Combobox(self, values=products,state=READABLE) self.productsCombo.place(x=10, y=25)
I am not going to comment on all the objects in the form, but I will note the two buttons, briefly. The first button is used to save the user review. It calls a method called insertReview().
save=Button(self.master, text="Save Review",command = self.insertReview) save.place(x=10, y=360)
Here is the method the button calls that inserts the material from the form.
def insertReview(self): p=self.productsCombo.get() email=self.emailEntry.get() r=self.rating.get() rev=self.review.get("1.0",END) revDate=time.strftime("%c") document = { "product" : p, "email" : email, "date" : revDate, "rating" : r, "reveiw" : rev } md = MongoData.MongoData() result=md.insertReview(document) insertResult=Label(self, text=result) insertResult.place(x=10, y=385)
The second command is to exit the program. It uses a lambda pointer so that the button can call itself and execute a built in method in its own constructor. It kills the program, but doesn't close the form. A bug to work out later.
exit=Button(self.master, text="Exit",command = lambda:exit.quit()) exit.place(x=100, y=360)
Here is the complete code for the Windows class
from tkinter import * from tkinter import ttk import ProductManagement import MongoData import time #class for creating a window and an #entry form for a new review #it inherits from tkinter.Frame #I used absolute placement #instead of a grid, which would #probably provide more flexibility class Window(Frame): def __init__(self, master=None): Frame.__init__(self, master) self.master = master self.init_window() #Creation of init_window def init_window(self): # changing the title of the master widget self.master.title("TechStore") # allowing the widget to take the full space of the root window self.pack(fill=BOTH, expand=1) # creating a label instance self.prompt = Label(self, text="Choose a product to Review") # placing the lable on the window self.prompt.place(x=10, y=0) #calling the product management class #to get the products pm = ProductManagement.ProductManagement() #making sure the product list is populated pm.populateProducts() products=pm.getProducts() #creating the Combobox and populating it with products self.productsCombo=ttk.Combobox(self, values=products,state=READABLE) self.productsCombo.place(x=10, y=25) # creating email label self.emailLabel=Label(self, text="Enter your email") self.emailLabel.place(x=10, y=55) #creating email entry box self.emailEntry=Entry(self) self.emailEntry.place(x=10, y=75) #creating the rating label self.ratingLabel=Label(self, text="Rate the product 1 to 5") self.ratingLabel.place(x=10, y=105) #creating the Entry for ratings self.rating=Entry(self) self.rating.place(x=10, y=125) #creating the review label self.reviewLabel =Label(self, text="Enter your review") self.reviewLabel.place(x=10, y=150) #creating the multiline Text enty #I wanted to add a scollbar, but every #attempt at it made the text box take #over the whole screen self.review =Text(self, height=10, width=50) self.review.place(x=10, y=170) #add the save review button save=Button(self.master, text="Save Review",command = self.insertReview) save.place(x=10, y=360) #add the exit button, which kills the window #but doesn't make it disappear #the lambda allows the button to contain #the quit command in its own constructor exit=Button(self.master, text="Exit",command = lambda:exit.quit()) exit.place(x=100, y=360) #this method takes the values from the combo #and text boxes and passes them to #the MongoData class where they are #inserted. The structure of the review #is somewhat different and simpler #than the original in the Mongo examples def insertReview(self): p=self.productsCombo.get() email=self.emailEntry.get() r=self.rating.get() rev=self.review.get("1.0",END) revDate=time.strftime("%c") document = { "product" : p, "email" : email, "date" : revDate, "rating" : r, "reveiw" : rev } md = MongoData.MongoData() result=md.insertReview(document) insertResult=Label(self, text=result) insertResult.place(x=10, y=385) root = Tk() #size of the window root.geometry("500x400") app = Window(root) root.mainloop()
It is important to note that the Mongo server must be running for the program to execute. Here is a screenshot of the program, after having filled in all the entry boxes and clicked the save button:
All the code, including the data classes https://github.com/spconger/ProductReviewPythonMongo
No comments:
Post a Comment