32

I'm building an application in Flask and I have several SQLAlchemy models defined. I have a dictionary with key/value pairs for each of the model types.

I want a generalised insert using a dictionary... would this require a mapper? I know that wtforms.ext.sqlalchemy.orm.model_form() generates an object with populate_obj(model) so it is possible. I've combed through the documentation but can't find it. I can perform the commit later, but need a shortcut to populate the object for now. Please, does anyone have expertise?

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy

app = Flask(__name__)
db = SQLAlchemy()
db.init_app(app)

employee_data = {'firstname':'John','lastname':'Smith'}
project_data = {'name':'project1'}

dict_generalised_insert(model=Employee,dictionary=employee_data)
dict_generalised_insert(model=Project,dictionary=project_data)

def dict_generalised_insert(model=None,dictionary={})
    obj = model.model() 
    obj.populate_obj(dictionary) # ???
    return obj

class Employee(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    firstname = db.Column(db.String(80))
    lastname = db.Column(db.String(80))

class Project(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80))
Richard Lee
  • 335
  • 1
  • 3
  • 8
  • Is there a reason you aren't just creating an instance of your model classes and saving them? – kylieCatt Jul 31 '15 at 16:03
  • I am loading in via CSV. I'd like my finite state machine to be as DRY as possible. – Richard Lee Jul 31 '15 at 16:10
  • I don't really see what that has to with using the module the way it was designed. You can unpack your dict in to the model constructor and save add it from there, you don't have to repeat any code. As it looks to me you are creating code to do things the module already does. – kylieCatt Jul 31 '15 at 16:16
  • I'm looking for a dictionary to model add setter, an equivalent to populate_obj(model) found in wtforms.ext.sqlalchemy.orm I'm not sure how to unpack a dict into a model constructor in a generalised fashion (so that the unpack dict to model works for both Employee and Project) – Richard Lee Jul 31 '15 at 16:22
  • 2
    `obj = Object(**dict)`. Then `db.session.add(obj); db.session.commit()` – kylieCatt Jul 31 '15 at 16:23
  • thanks a lot what was missing was the ** in **dict – Richard Lee Jul 31 '15 at 16:41

1 Answers1

67

The idiomatic way to unpack a dictionary is to use the double star operator **.

To use it with flask-sqlalchemy:

class Employee(db.Model)
    id = db.Column(...)
    firstname = db.Column(...)
    lastname = db.Column(...)

employee_data = {'firstname':'John','lastname':'Smith'}
employee = Employee(**employee_data)
db.session.add(employee)
db.session.commit()

Be aware that the keys in the dictionary have to match the attribute names of the class. Unpacking in this manner is the same as:

employee = Employee(firstname='John', lastname='Smith')

You can also do this with a list if you define an __init__ (or other method) with positional arguments however you only use a single star:

def __init__(self, firstname, lastname):
    self.firstname = firstname
    self.lastname = lastname

employee_data = ['John', 'Smith']
employee = Employee(*employee_data)
...

Note here the order of the values is what's important.

kylieCatt
  • 10,672
  • 5
  • 43
  • 51