Google App Engine: Import CSV to Datastore

Processing CSV Data with the Google App Engine is a two-step process. First, you need to upload the data and store it in the blob store. Then you retrieve the file and process the information and save it to the Datastore(Database). You can process the CSV data with the standard python tools from the CSV-module, however, instead of parsing a file you must parse a BlobReader.

import csv
import webapp2
from google.appengine.ext import blobstore
from google.appengine.ext.webapp import blobstore_handlers
from google.appengine.ext import db


class MainHandler(webapp2.RequestHandler):
    def get(self):
        upload_url = blobstore.create_upload_url('/upload')

        html_string = """
         <form action="%s" method="POST" enctype="multipart/form-data">
        Upload File:
        <input type="file" name="file"> <br>
        <input type="submit" name="submit" value="Submit">
        </form>""" % upload_url

        self.response.write(html_string)


class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
    def post(self):
        upload_files = self.get_uploads('file')  # 'file' is file upload field in the form
        blob_info = upload_files[0]
        process_csv(blob_info)

        blobstore.delete(blob_info.key())  # optional: delete file after import
        self.redirect("/")


def process_csv(blob_info):
    blob_reader = blobstore.BlobReader(blob_info.key())
    reader = csv.reader(blob_reader, delimiter=';')
    for row in reader:
        date, data, value = row
        entry = EntriesDB(date=date, data=data, value=int(value))
        entry.put()


class EntriesDB(db.Model):
    date = db.DateProperty()
    data = db.StringProperty()
    value = db.IntegerProperty()

app = webapp2.WSGIApplication([
    ('/', MainHandler),
    ('/upload', UploadHandler)
], debug=True)

PySide: QPushbutton Text below Icon

Apparently using a QPushbutton with an Icon does not work. As alternative, I am going to use a QToolbutton.

import sys
from PySide.QtCore import *
from PySide.QtGui import *

class Widget(QWidget):
    
    def __init__(self, parent= None):
        super(Widget, self).__init__()
        
        layout = QVBoxLayout(self)
        
        #QToolButton
        btn = QToolButton()
        btn.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        btn.setText("test")
        btn.setIcon(btn.style().standardIcon(QStyle.SP_DirIcon))
        btn.setIconSize(QSize(54,54))
        
        layout.addWidget(btn)
        
        self.setLayout(layout)
        
        
if __name__ == '__main__':
    app = QApplication(sys.argv)
    
    dialog = Widget()
    dialog.show()

    app.exec_()

PySide: QVBoxLayout with QScrollArea

Here is an example that adds Scrollbars to a QVBoxLayout. The one thing that tripped me up was that you need to explicitly create a Widget for the QScrollArea.

import sys
from PySide.QtCore import *
from PySide.QtGui import *

class Widget(QWidget):
    
    def __init__(self, parent= None):
        super(Widget, self).__init__()
        self.setFixedHeight(200)
        
        #Container Widget        
        widget = QWidget()
        #Layout of Container Widget
        layout = QVBoxLayout(self)
        for _ in range(20):
            btn = QPushButton("test")
            layout.addWidget(btn)
        widget.setLayout(layout)

        #Scroll Area Properties
        scroll = QScrollArea()
        scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        scroll.setWidgetResizable(False)
        scroll.setWidget(widget)
        
        #Scroll Area Layer add 
        vLayout = QVBoxLayout(self)
        vLayout.addWidget(scroll)
        self.setLayout(vLayout)
        
        
if __name__ == '__main__':
    app = QApplication(sys.argv)
    
    dialog = Widget()
    dialog.show()

    app.exec_()

PySide: QTreeListWidget deleting an Item, editing an Item

This example creates a QTreeListWidget to display a folder-structure.

import sys, os
from PySide.QtCore import *
from PySide.QtGui import *

class TreeTest(QTreeWidget):
    
    def __init__(self, parent = None):
        super(TreeTest, self).__init__(parent)
        self.setColumnCount(1)
        self.setHeaderLabel("Folders")
        
        actionEdit = QAction("New Folder", self)
        actionEdit.triggered.connect(self.addItemAction)
        self.setContextMenuPolicy(Qt.ActionsContextMenu)
        self.addAction(actionEdit)
        
        actionDelete = QAction("Delete", self)
        actionDelete.triggered.connect(self.deleteItem)
        self.addAction(actionDelete)
        
        self.style()
        
    def addItem(self, name, parent):
        self.expandItem(parent) 
        item = QTreeWidgetItem(parent)
        item.setText(0, name)
        #It is important to set the Flag Qt.ItemIsEditable
        item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled | Qt.ItemIsDragEnabled | Qt.ItemIsEditable)

        item.setIcon(0,self.style().standardIcon(QStyle.SP_DirIcon))
        return item
    
    def addItemAction(self):
        parent = self.currentItem()
        if parent is None:
            parent = self.invisibleRootItem()
        new_item = self.addItem("New Folder", parent)
        self.editItem(new_item)
    
    def deleteItem(self):
        root = self.invisibleRootItem()
        for item in self.selectedItems():
            (item.parent() or root).removeChild(item)
    
if __name__ == '__main__':
    app = QApplication(sys.argv)
    test = QWidget()
    treeWidget = TreeTest()
    layout = QHBoxLayout()
    layout.addWidget(treeWidget)
    
    test.setLayout(layout)
    test.show()
    
    treeWidget.addItem("top", treeWidget.invisibleRootItem())
    item = treeWidget.addItem("item", treeWidget.invisibleRootItem())
    treeWidget.addItem("subitem", item)
    
    app.exec_()

PySide: Using standard system Icons

You can add Icons to many types of QWidgets. PySide provides you with a method to access the native system icons. A complete list of icons can be found here:PySide.QtGui.PySide.QtGui.QStyle.StandardPixmap

To apply the QIcon you need to

btn = QPushButton('Folder')
style = btn.style()
icon = style.standardIcon(QStyle.SP_DirIcon)
btn.setIcon(icon)
#or short:
btn.setIcon(btn.style().standardIcon(QStyle.SP_DirIcon))

Here a small example:

import sys
from PySide.QtCore import *
from PySide.QtGui import *

class Widget(QWidget):
    
    def __init__(self, parent= None):
        super(Widget, self).__init__()
        
        btn_folder = QPushButton('Folder')
        btn_folder.setIcon(self.style().standardIcon(QStyle.SP_DirIcon))
        
        btn_one = QPushButton('Play')
        btn_one.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        
        btn_two = QPushButton('Stop')
        btn_two.setIcon(self.style().standardIcon(QStyle.SP_MediaStop))
        
        btn_three = QPushButton('Pause')
        btn_three.setIcon(self.style().standardIcon(QStyle.SP_MediaPause))
        
        layout = QHBoxLayout()
        layout.addWidget(btn_folder)
        layout.addWidget(btn_one)
        layout.addWidget(btn_two)
        layout.addWidget(btn_three)
        
        self.setLayout(layout)
        
if __name__ == '__main__':
    app = QApplication(sys.argv)
    
    dialog = Widget()
    dialog.show()

    app.exec_()

PySide: QMessageBox with QCheckBox

The QMessageBox is very useful for creating standard filesystem dialogs (it even comes with alert sounds) and is limited to display an icon, text and standard buttons. If you want to add something extra like a checkbox for “do not ask me again”, you need to extend the base class.

import sys
from PySide.QtCore import *
from PySide.QtGui import *

class DialogWithCheckBox(QMessageBox):

    def __init__(self, parent= None):
        super(DialogWithCheckBox, self).__init__()

        self.checkbox = QCheckBox()
        #Access the Layout of the MessageBox to add the Checkbox
        layout = self.layout()
        layout.addWidget(self.checkbox, 1,2)

    def exec_(self, *args, **kwargs):
        """
        Override the exec_ method so you can return the value of the checkbox
        """
        return QMessageBox.exec_(self, *args, **kwargs), self.checkbox.isChecked()

class ExampleCheckbox(DialogWithCheckBox):

    def __init__(self, parent=None):
        super(ExampleCheckbox, self).__init__()
        self.setWindowTitle("Dialog with CheckBox")
        self.setText("Isn't this checkbox beautiful?")
        self.checkbox.setText("Do not ask again")
        self.setStandardButtons(QMessageBox.Cancel |QMessageBox.Ok)
        self.setDefaultButton(QMessageBox.Cancel)
        self.setIcon(QMessageBox.Warning)

if __name__ == '__main__':
    app = QApplication(sys.argv)

    dialog = ExampleCheckbox()
    answer = dialog.exec_()

    # Example how to handle the response
    if answer[1] == True:
        if answer[0] == int(QMessageBox.Ok):
            print ("Ok button pressed")
        print ("handle checkbox has been activated")
    else:
        print ("handle checkbox not activated")

    app.exec_() 

PySide: Rightclick Button Menu

PySide (www.pyside.org) is an awesome Framework that allows you to use Qt with Python. Installation is as straightforward as typing

pip install pyside

I will be creating a menu that opens with a right click. This menu is called “Context Menu” in QT. In this example, the right-click menu on the button removes the button at runtime.

import sys
from PySide.QtCore import *
from PySide.QtGui import *

class RightClickMenuButton(QPushButton):

    def __init__(self, name, parent = None):
        super(RightClickMenuButton, self).__init__(name)

        self.setContextMenuPolicy(Qt.ActionsContextMenu)
        self.addMenuActions();

    def addMenuActions(self):
        delete = QAction(self)
        delete.setText("remove")
        delete.triggered.connect(self.removeButton)
        self.addAction(delete)

    def removeButton(self):
        self.deleteLater()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    test = QWidget()
    test.resize(250, 150)

    layout = QHBoxLayout()
    layout.addWidget(RightClickMenuButton("Test Btn"))
    test.setLayout(layout)

    test.show()
    app.exec_()