├── .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 |
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 |
--------------------------------------------------------------------------------