├── .gitignore ├── MongoDB Python.pdf ├── README.md ├── gui ├── __init__.py ├── icons.qrc ├── icons_rc.py ├── images │ ├── add-icon.png │ ├── app.png │ ├── photo.jpg │ └── remove.png ├── main.py └── main.ui ├── icons_rc.py ├── lib ├── __init__.py ├── customModel.py └── databaseOperations.py └── mongo_python.py /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | *.pyc -------------------------------------------------------------------------------- /MongoDB Python.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfxpipeline/Python-MongoDB-Example/d5d4deff33e960ac7837a65f4e4404b5b4231a34/MongoDB Python.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Python-MongoDB-Example 2 | A Live working Example Application of Python, Qt, PySide2, MongoDB, PyMongo, QTableView, QAbstractTableModel 3 | 4 | # A Complete Video Tutorial of this application is Available 5 | #### https://www.youtube.com/vfxpipeline 6 | #### Please Subscribe to my youtube channel to appriciate me. 7 | 8 | # What is this application ? 9 | This is a python application to load mongodb database data in pyside2 interface 10 | 11 | # Requirements 12 | * Python3.6 13 | * pip install pymongo==3.7.2 - MongoDB Python Driver 14 | * MongoDB 4.0.4 - Database Server 15 | * (Optional)MongoDB Compass 1.16.3 - To view database 16 | 17 | # What MongoDB Operation covered in this application 18 | 1. Connect to MongoDB database 19 | 2. Create new database 20 | 3. Create new collection 21 | 4. Insert new data 22 | 5. Update existing data 23 | 6. Query Data 24 | 7. Remove Data 25 | 8. Store image on MongoDb Database 26 | 27 | 28 | # What is the core logics related to PySide2 29 | 1. Create a TableView 30 | 2. Create a QAbstractTableModel 31 | 3. Load MongoDB Database data in QAbstractTableModel 32 | 4. Make QAbstractTableModel rows inline editable to edit database 33 | 5. Create (Add Row, Remove Row) context Menu on Tableview 34 | 6. Create Dynamic Headers in QAbstractTableModel 35 | 7. Add New Empty Row in QAbstractTableModel 36 | 8. Remove row from QAbstractTableModel 37 | 9. Edit Cell value in QAbstractTableModel 38 | 10. Display image in column of QAbstractTableModel 39 | 11. On double click on image a QFileDialog will open to change image 40 | -------------------------------------------------------------------------------- /gui/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Name: Studio Desktop Client 3 | Author : Rajiv Sharma 4 | Developer Website : www.hqvfx.com 5 | Developer Email : rajiv@hqvfx.com 6 | Date Started : 16 sept 2018 7 | Date Modified : 8 | Description : Desktop client for Stdio Line Production pipeline 9 | 10 | Download Application from : www.hqvfx.com/downloads 11 | Source Code Website : www.github.com/hqvfx 12 | Free Video Tutorials : www.youtube.com/vfxpipeline 13 | 14 | Copyright (c) 2018, HQVFX(www.hqvfx.com) . All rights reserved. 15 | Redistribution and use in source and binary forms, with or without 16 | modification, are permitted provided that the following conditions are 17 | met: 18 | 19 | * Redistributions of source code must retain the above copyright 20 | notice, this list of conditions and the following disclaimer. 21 | 22 | * Redistributions in binary form must reproduce the above copyright 23 | notice, this list of conditions and the following disclaimer in the 24 | documentation and/or other materials provided with the distribution. 25 | 26 | * Neither the name of HQVFX(www.hqvfx.com) nor the names of any 27 | other contributors to this software may be used to endorse or 28 | promote products derived from this software without specific prior written permission. 29 | 30 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 31 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 32 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 33 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 34 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 35 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 36 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 37 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 38 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 39 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 40 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41 | """ -------------------------------------------------------------------------------- /gui/icons.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | images/photo.jpg 4 | images/add-icon.png 5 | images/app.png 6 | images/remove.png 7 | 8 | 9 | -------------------------------------------------------------------------------- /gui/images/add-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfxpipeline/Python-MongoDB-Example/d5d4deff33e960ac7837a65f4e4404b5b4231a34/gui/images/add-icon.png -------------------------------------------------------------------------------- /gui/images/app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfxpipeline/Python-MongoDB-Example/d5d4deff33e960ac7837a65f4e4404b5b4231a34/gui/images/app.png -------------------------------------------------------------------------------- /gui/images/photo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfxpipeline/Python-MongoDB-Example/d5d4deff33e960ac7837a65f4e4404b5b4231a34/gui/images/photo.jpg -------------------------------------------------------------------------------- /gui/images/remove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfxpipeline/Python-MongoDB-Example/d5d4deff33e960ac7837a65f4e4404b5b4231a34/gui/images/remove.png -------------------------------------------------------------------------------- /gui/main.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'main.ui', 4 | # licensing of 'main.ui' applies. 5 | # 6 | # Created: Sat Dec 8 08:45:16 2018 7 | # by: pyside2-uic running on PySide2 5.11.1 8 | # 9 | # WARNING! All changes made in this file will be lost! 10 | 11 | from PySide2 import QtCore, QtGui, QtWidgets 12 | 13 | class Ui_MainWindow(object): 14 | def setupUi(self, MainWindow): 15 | MainWindow.setObjectName("MainWindow") 16 | MainWindow.resize(800, 600) 17 | icon = QtGui.QIcon() 18 | icon.addPixmap(QtGui.QPixmap(":/icons/images/app.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) 19 | MainWindow.setWindowIcon(icon) 20 | self.centralwidget = QtWidgets.QWidget(MainWindow) 21 | self.centralwidget.setObjectName("centralwidget") 22 | self.gridLayout_3 = QtWidgets.QGridLayout(self.centralwidget) 23 | self.gridLayout_3.setObjectName("gridLayout_3") 24 | self.frame_2 = QtWidgets.QFrame(self.centralwidget) 25 | self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel) 26 | self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised) 27 | self.frame_2.setObjectName("frame_2") 28 | self.gridLayout = QtWidgets.QGridLayout(self.frame_2) 29 | self.gridLayout.setObjectName("gridLayout") 30 | self.label = QtWidgets.QLabel(self.frame_2) 31 | self.label.setMaximumSize(QtCore.QSize(40, 40)) 32 | self.label.setText("") 33 | self.label.setPixmap(QtGui.QPixmap(":/icons/images/app.png")) 34 | self.label.setScaledContents(True) 35 | self.label.setObjectName("label") 36 | self.gridLayout.addWidget(self.label, 0, 0, 1, 1) 37 | self.label_2 = QtWidgets.QLabel(self.frame_2) 38 | font = QtGui.QFont() 39 | font.setPointSize(18) 40 | self.label_2.setFont(font) 41 | self.label_2.setObjectName("label_2") 42 | self.gridLayout.addWidget(self.label_2, 0, 1, 1, 1) 43 | self.gridLayout_3.addWidget(self.frame_2, 0, 0, 1, 1) 44 | self.frame = QtWidgets.QFrame(self.centralwidget) 45 | self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel) 46 | self.frame.setFrameShadow(QtWidgets.QFrame.Raised) 47 | self.frame.setObjectName("frame") 48 | self.gridLayout_2 = QtWidgets.QGridLayout(self.frame) 49 | self.gridLayout_2.setObjectName("gridLayout_2") 50 | self.tableView = QtWidgets.QTableView(self.frame) 51 | self.tableView.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection) 52 | self.tableView.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) 53 | self.tableView.setIconSize(QtCore.QSize(50, 50)) 54 | self.tableView.setSortingEnabled(True) 55 | self.tableView.setObjectName("tableView") 56 | self.tableView.horizontalHeader().setCascadingSectionResizes(True) 57 | self.tableView.horizontalHeader().setStretchLastSection(True) 58 | self.tableView.verticalHeader().setCascadingSectionResizes(False) 59 | self.gridLayout_2.addWidget(self.tableView, 0, 0, 1, 1) 60 | self.tableView_2 = QtWidgets.QTableView(self.frame) 61 | self.tableView_2.setObjectName("tableView_2") 62 | self.gridLayout_2.addWidget(self.tableView_2, 0, 1, 1, 1) 63 | self.gridLayout_3.addWidget(self.frame, 1, 0, 1, 1) 64 | self.tableView_3 = QtWidgets.QTableView(self.centralwidget) 65 | self.tableView_3.setObjectName("tableView_3") 66 | self.gridLayout_3.addWidget(self.tableView_3, 2, 0, 1, 1) 67 | MainWindow.setCentralWidget(self.centralwidget) 68 | self.menubar = QtWidgets.QMenuBar(MainWindow) 69 | self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21)) 70 | self.menubar.setObjectName("menubar") 71 | self.menuAbout = QtWidgets.QMenu(self.menubar) 72 | self.menuAbout.setObjectName("menuAbout") 73 | MainWindow.setMenuBar(self.menubar) 74 | self.statusbar = QtWidgets.QStatusBar(MainWindow) 75 | self.statusbar.setObjectName("statusbar") 76 | MainWindow.setStatusBar(self.statusbar) 77 | self.actionAbout_Application = QtWidgets.QAction(MainWindow) 78 | self.actionAbout_Application.setIcon(icon) 79 | self.actionAbout_Application.setObjectName("actionAbout_Application") 80 | self.menuAbout.addAction(self.actionAbout_Application) 81 | self.menubar.addAction(self.menuAbout.menuAction()) 82 | 83 | self.retranslateUi(MainWindow) 84 | QtCore.QMetaObject.connectSlotsByName(MainWindow) 85 | 86 | def retranslateUi(self, MainWindow): 87 | MainWindow.setWindowTitle(QtWidgets.QApplication.translate("MainWindow", "Python MongoDB Application", None, -1)) 88 | self.label_2.setText(QtWidgets.QApplication.translate("MainWindow", "MongoDB Database Application (TreeView and Custom Model)", None, -1)) 89 | self.menuAbout.setTitle(QtWidgets.QApplication.translate("MainWindow", "About", None, -1)) 90 | self.actionAbout_Application.setText(QtWidgets.QApplication.translate("MainWindow", "About Application", None, -1)) 91 | 92 | import icons_rc 93 | -------------------------------------------------------------------------------- /gui/main.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 800 10 | 600 11 | 12 | 13 | 14 | Python MongoDB Application 15 | 16 | 17 | 18 | :/icons/images/app.png:/icons/images/app.png 19 | 20 | 21 | 22 | 23 | 24 | 25 | QFrame::StyledPanel 26 | 27 | 28 | QFrame::Raised 29 | 30 | 31 | 32 | 33 | 34 | 35 | 40 36 | 40 37 | 38 | 39 | 40 | 41 | 42 | 43 | :/icons/images/app.png 44 | 45 | 46 | true 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 18 55 | 56 | 57 | 58 | MongoDB Database Application (TreeView and Custom Model) 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | QFrame::StyledPanel 69 | 70 | 71 | QFrame::Raised 72 | 73 | 74 | 75 | 76 | 77 | QAbstractItemView::SingleSelection 78 | 79 | 80 | QAbstractItemView::SelectRows 81 | 82 | 83 | 84 | 50 85 | 50 86 | 87 | 88 | 89 | true 90 | 91 | 92 | true 93 | 94 | 95 | true 96 | 97 | 98 | false 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 0 117 | 0 118 | 800 119 | 21 120 | 121 | 122 | 123 | 124 | About 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | :/icons/images/app.png:/icons/images/app.png 135 | 136 | 137 | About Application 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /lib/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Name: Studio Desktop Client 3 | Author : Rajiv Sharma 4 | Developer Website : www.hqvfx.com 5 | Developer Email : rajiv@hqvfx.com 6 | Date Started : 16 sept 2018 7 | Date Modified : 8 | Description : Desktop client for Stdio Line Production pipeline 9 | 10 | Download Application from : www.hqvfx.com/downloads 11 | Source Code Website : www.github.com/hqvfx 12 | Free Video Tutorials : www.youtube.com/vfxpipeline 13 | 14 | Copyright (c) 2018, HQVFX(www.hqvfx.com) . All rights reserved. 15 | Redistribution and use in source and binary forms, with or without 16 | modification, are permitted provided that the following conditions are 17 | met: 18 | 19 | * Redistributions of source code must retain the above copyright 20 | notice, this list of conditions and the following disclaimer. 21 | 22 | * Redistributions in binary form must reproduce the above copyright 23 | notice, this list of conditions and the following disclaimer in the 24 | documentation and/or other materials provided with the distribution. 25 | 26 | * Neither the name of HQVFX(www.hqvfx.com) nor the names of any 27 | other contributors to this software may be used to endorse or 28 | promote products derived from this software without specific prior written permission. 29 | 30 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 31 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 32 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 33 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 34 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 35 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 36 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 37 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 38 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 39 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 40 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41 | """ -------------------------------------------------------------------------------- /lib/customModel.py: -------------------------------------------------------------------------------- 1 | """ 2 | Name: Custom Table Models to load data in Tree view 3 | Author : Rajiv Sharma 4 | Developer Website : www.hqvfx.com 5 | Developer Email : rajiv@hqvfx.com 6 | Date Started : 12 December 2018 7 | Date Modified : 8 | Description : Desktop client for Stdio Line Production pipeline 9 | 10 | Download Application from : www.hqvfx.com/downloads 11 | Source Code Website : www.github.com/hqvfx 12 | Free Video Tutorials : www.youtube.com/vfxpipeline 13 | 14 | Copyright (c) 2018, HQVFX(www.hqvfx.com) . All rights reserved. 15 | Redistribution and use in source and binary forms, with or without 16 | modification, are permitted provided that the following conditions are 17 | met: 18 | 19 | * Redistributions of source code must retain the above copyright 20 | notice, this list of conditions and the following disclaimer. 21 | 22 | * Redistributions in binary form must reproduce the above copyright 23 | notice, this list of conditions and the following disclaimer in the 24 | documentation and/or other materials provided with the distribution. 25 | 26 | * Neither the name of HQVFX(www.hqvfx.com) nor the names of any 27 | other contributors to this software may be used to endorse or 28 | promote products derived from this software without specific prior written permission. 29 | 30 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 31 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 32 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 33 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 34 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 35 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 36 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 37 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 38 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 39 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 40 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41 | """ 42 | from PySide2 import QtWidgets 43 | from PySide2 import QtCore 44 | from PySide2 import QtGui 45 | from lib import databaseOperations 46 | 47 | 48 | class CustomTableModel(QtCore.QAbstractTableModel): 49 | """ 50 | Custom Table Model to handle MongoDB Data 51 | """ 52 | def __init__(self, data): 53 | QtCore.QAbstractTableModel.__init__(self) 54 | self.user_data = data 55 | self.columns = list(self.user_data[0].keys()) 56 | 57 | def flags(self, index): 58 | """ 59 | Make table editable. 60 | make first column non editable 61 | :param index: 62 | :return: 63 | """ 64 | if index.column() > 0: 65 | return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable 66 | elif index.column() == 1: 67 | return QtCore.Qt.DecorationRole 68 | else: 69 | return QtCore.Qt.ItemIsSelectable 70 | 71 | def rowCount(self, *args, **kwargs): 72 | """ 73 | set row counts 74 | :param args: 75 | :param kwargs: 76 | :return: 77 | """ 78 | return len(self.user_data) 79 | 80 | def columnCount(self, *args, **kwargs): 81 | """ 82 | set column counts 83 | :param args: 84 | :param kwargs: 85 | :return: 86 | """ 87 | return len(self.columns) 88 | 89 | def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole): 90 | """ 91 | set column header data 92 | :param section: 93 | :param orientation: 94 | :param role: 95 | :return: 96 | """ 97 | if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole: 98 | return self.columns[section].title() 99 | 100 | def data(self, index, role): 101 | """ 102 | Display Data in table cells 103 | :param index: 104 | :param role: 105 | :return: 106 | """ 107 | row = self.user_data[index.row()] 108 | column = self.columns[index.column()] 109 | try: 110 | if index.column() == 1: 111 | selected_row = self.user_data[index.row()] 112 | image_data = selected_row['photo'] 113 | image = QtGui.QImage() 114 | image.loadFromData(image_data) 115 | icon = QtGui.QIcon() 116 | icon.addPixmap(QtGui.QPixmap.fromImage(image)) 117 | return icon 118 | elif role == QtCore.Qt.DisplayRole: 119 | return str(row[column]) 120 | except KeyError: 121 | return None 122 | 123 | def setData(self, index, value, role=QtCore.Qt.EditRole): 124 | """ 125 | Edit data in table cells 126 | :param index: 127 | :param value: 128 | :param role: 129 | :return: 130 | """ 131 | if index.isValid(): 132 | selected_row = self.user_data[index.row()] 133 | selected_column = self.columns[index.column()] 134 | selected_row[selected_column] = value 135 | self.dataChanged.emit(index, index, (QtCore.Qt.DisplayRole, )) 136 | ok = databaseOperations.update_existing(selected_row['_id'], selected_row) 137 | if ok: 138 | return True 139 | return False 140 | 141 | def insertRows(self): 142 | row_count = len(self.user_data) 143 | self.beginInsertRows(QtCore.QModelIndex(), row_count, row_count) 144 | empty_data = { key: None for key in self.columns if not key=='_id'} 145 | document_id = databaseOperations.insert_data(empty_data) 146 | new_data = databaseOperations.get_single_data(document_id) 147 | self.user_data.append(new_data) 148 | row_count += 1 149 | self.endInsertRows() 150 | return True 151 | 152 | def removeRows(self, position): 153 | row_count = self.rowCount() 154 | row_count -= 1 155 | self.beginRemoveRows(QtCore.QModelIndex(), row_count, row_count) 156 | row_id = position.row() 157 | document_id = self.user_data[row_id]['_id'] 158 | databaseOperations.remove_data(document_id) 159 | self.user_data.pop(row_id) 160 | self.endRemoveRows() 161 | return True 162 | 163 | 164 | class ProfilePictureDelegate(QtWidgets.QStyledItemDelegate): 165 | """ 166 | This will open QFileDialog to select image 167 | """ 168 | def __init__(self): 169 | QtWidgets.QStyledItemDelegate.__init__(self) 170 | 171 | def createEditor(self, parent, option, index): 172 | editor = QtWidgets.QFileDialog() 173 | return editor 174 | 175 | def setModelData(self, editor, model, index): 176 | selected_file =editor.selectedFiles()[0] 177 | image = open(selected_file, 'rb').read() 178 | model.setData(index, image) 179 | 180 | 181 | class InLineEditDelegate(QtWidgets.QItemDelegate): 182 | """ 183 | Delegate is important for inline editing of cells 184 | """ 185 | 186 | def createEditor(self, parent, option, index): 187 | return super(InLineEditDelegate, self).createEditor(parent, option, index) 188 | 189 | def setEditorData(self, editor, index): 190 | text = index.data(QtCore.Qt.EditRole) or index.data(QtCore.Qt.DisplayRole) 191 | editor.setText(str(text)) -------------------------------------------------------------------------------- /lib/databaseOperations.py: -------------------------------------------------------------------------------- 1 | """ 2 | Name: MongoDB Database Operations 3 | Author : Rajiv Sharma 4 | Developer Website : www.hqvfx.com 5 | Developer Email : rajiv@hqvfx.com 6 | Date Started : 12 December 2018 7 | Date Modified : 8 | Description : communicate with mongodb database from python 9 | 10 | Download Application from : www.hqvfx.com/downloads 11 | Source Code Website : www.github.com/hqvfx 12 | Free Video Tutorials : www.youtube.com/vfxpipeline 13 | 14 | Copyright (c) 2018, HQVFX(www.hqvfx.com) . All rights reserved. 15 | Redistribution and use in source and binary forms, with or without 16 | modification, are permitted provided that the following conditions are 17 | met: 18 | 19 | * Redistributions of source code must retain the above copyright 20 | notice, this list of conditions and the following disclaimer. 21 | 22 | * Redistributions in binary form must reproduce the above copyright 23 | notice, this list of conditions and the following disclaimer in the 24 | documentation and/or other materials provided with the distribution. 25 | 26 | * Neither the name of HQVFX(www.hqvfx.com) nor the names of any 27 | other contributors to this software may be used to endorse or 28 | promote products derived from this software without specific prior written permission. 29 | 30 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 31 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 32 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 33 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 34 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 35 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 36 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 37 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 38 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 39 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 40 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41 | """ 42 | import pymongo 43 | from bson import ObjectId 44 | 45 | 46 | # CONNECT TO DATABASE 47 | connection = pymongo.MongoClient("localhost", 27017) 48 | 49 | # CREATE DATABASE 50 | database = connection['my_database'] 51 | # CREATE COLLECTION 52 | collection = database['my_collection'] 53 | print("Database connected") 54 | 55 | 56 | def insert_data(data): 57 | """ 58 | Insert new data or document in collection 59 | :param data: 60 | :return: 61 | """ 62 | document = collection.insert_one(data) 63 | return document.inserted_id 64 | 65 | 66 | def update_or_create(document_id, data): 67 | """ 68 | This will create new document in collection 69 | IF same document ID exist then update the data 70 | :param document_id: 71 | :param data: 72 | :return: 73 | """ 74 | # TO AVOID DUPLICATES - THIS WILL CREATE NEW DOCUMENT IF SAME ID NOT EXIST 75 | document = collection.update_one({'_id': ObjectId(document_id)}, {"$set": data}, upsert=True) 76 | return document.acknowledged 77 | 78 | 79 | def get_single_data(document_id): 80 | """ 81 | get document data by document ID 82 | :param document_id: 83 | :return: 84 | """ 85 | data = collection.find_one({'_id': ObjectId(document_id)}) 86 | return data 87 | 88 | 89 | def get_multiple_data(): 90 | """ 91 | get document data by document ID 92 | :return: 93 | """ 94 | data = collection.find() 95 | return list(data) 96 | 97 | 98 | def update_existing(document_id, data): 99 | """ 100 | Update existing document data by document ID 101 | :param document_id: 102 | :param data: 103 | :return: 104 | """ 105 | document = collection.update_one({'_id': ObjectId(document_id)}, {"$set": data}) 106 | return document.acknowledged 107 | 108 | 109 | def remove_data(document_id): 110 | document = collection.delete_one({'_id': ObjectId(document_id)}) 111 | return document.acknowledged 112 | 113 | 114 | # CLOSE DATABASE 115 | connection.close() 116 | -------------------------------------------------------------------------------- /mongo_python.py: -------------------------------------------------------------------------------- 1 | """ 2 | Name: MongoDB Python Demo app 3 | Author : Rajiv Sharma 4 | Developer Website : www.hqvfx.com 5 | Developer Email : rajiv@hqvfx.com 6 | Date Started : 12 december 2018 7 | Date Modified : 8 | Description : Create tableView and create a custom model to populate data 9 | 10 | Download Application from : www.hqvfx.com/downloads 11 | Source Code Website : www.github.com/hqvfx 12 | Free Video Tutorials : www.youtube.com/vfxpipeline 13 | 14 | Copyright (c) 2018, HQVFX(www.hqvfx.com) . All rights reserved. 15 | Redistribution and use in source and binary forms, with or without 16 | modification, are permitted provided that the following conditions are 17 | met: 18 | 19 | * Redistributions of source code must retain the above copyright 20 | notice, this list of conditions and the following disclaimer. 21 | 22 | * Redistributions in binary form must reproduce the above copyright 23 | notice, this list of conditions and the following disclaimer in the 24 | documentation and/or other materials provided with the distribution. 25 | 26 | * Neither the name of HQVFX(www.hqvfx.com) nor the names of any 27 | other contributors to this software may be used to endorse or 28 | promote products derived from this software without specific prior written permission. 29 | 30 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 31 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 32 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 33 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 34 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 35 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 36 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 37 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 38 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 39 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 40 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41 | """ 42 | 43 | from PySide2 import QtWidgets 44 | from PySide2 import QtGui 45 | from PySide2 import QtCore 46 | from gui import main 47 | from lib import databaseOperations 48 | from lib import customModel 49 | 50 | 51 | class PythonMongoDB(main.Ui_MainWindow, QtWidgets.QMainWindow): 52 | def __init__(self): 53 | super(PythonMongoDB, self).__init__() 54 | self.setupUi(self) 55 | 56 | # data = {'photo': ":/icons/images/photo.jpg", 'name': 'rajiv'} 57 | # databaseOperations.insert_data(data) 58 | 59 | self.user_data = databaseOperations.get_multiple_data() 60 | self.model = customModel.CustomTableModel(self.user_data) 61 | self.delegate = customModel.InLineEditDelegate() 62 | self.tableView.setModel(self.model) 63 | self.tableView.setItemDelegate(self.delegate) 64 | self.tableView.setItemDelegateForColumn(1, customModel.ProfilePictureDelegate()) 65 | self.tableView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) 66 | self.tableView.customContextMenuRequested.connect(self.context_menu) 67 | self.tableView.verticalHeader().setDefaultSectionSize(50) 68 | self.tableView.setColumnWidth(0, 30) 69 | self.tableView.hideColumn(0) 70 | self.tableView_2.setModel(self.model) 71 | self.tableView_3.setModel(self.model) 72 | 73 | def context_menu(self): 74 | menu = QtWidgets.QMenu() 75 | add_data = menu.addAction("Add New Data") 76 | add_data.setIcon(QtGui.QIcon(":/icons/images/add-icon.png")) 77 | add_data.triggered.connect(lambda: self.model.insertRows()) 78 | if self.tableView.selectedIndexes(): 79 | remove_data = menu.addAction("Remove Data") 80 | remove_data.setIcon(QtGui.QIcon(":/icons/images/remove.png")) 81 | remove_data.triggered.connect(lambda: self.model.removeRows(self.tableView.currentIndex())) 82 | cursor = QtGui.QCursor() 83 | menu.exec_(cursor.pos()) 84 | 85 | 86 | if __name__ == '__main__': 87 | app = QtWidgets.QApplication([]) 88 | my_app = PythonMongoDB() 89 | my_app.show() 90 | app.exec_() 91 | --------------------------------------------------------------------------------