Reputation: 766
In the following example code I illustrate how I solved passing the request from the controller to the model. Is there a better way to do this?
models/MyModel.py
from google.appengine.ext import db
class MyModel(db.model):
a = db.StringProperty(required=True)
b = db.StringProperty(required=True)
c = db.StringProperty(required=True)
class Update:
def __init__(self, x)
self.x = x
def do_something(self)
myquery = db.GqlQuery('SELECT * FROM MyModel WHERE a = :1' self.x)
v = myquery.get()
if not v:
somevalue = MyModel(a = self.request.get('a'), # Doesn't work unless
b = self.request.get('b'), # the request has been
c = self.request.get('c')) # passed
somevalue.put()
controllers/MyController.py
import webapp2
from models.MyModel import Update
class WebHandler(webapp2.RequestHandler):
def get(self):
var_x = "string"
var_y = "string"
z = Update(var_x)
z.request = self.request # <--- Is there a better way?
z.do_something()
Edit: (5/30/2012) I ended up creating a function to pass the request variables to the Model as arguments. I was hoping there was some python magic that would avoid all the repetition but I didn't find one.
Upvotes: 1
Views: 189
Reputation: 96920
You need a little more encapsulation. Another level of abstraction is useful.
Create a class representing the actual thing that you're using MyModel
to persist, with a
, b
, and c
attributes or properties:
class Thing(object):
def __init__(a, b, c):
self.a = a
self.b = b
self.c = c
This class doesn't know anything about requests, or the datastore, or persistence. It's where all the actual business logic surrounding the thing itself lives.
You can instantiate this class without needing a request or a database, and you can unit test all of the business logic without having to mock out any of GAE's plumbing.
You can then write code in your request handler that instantiates this thing, e.g.:
def get(request):
thing = Thing(a=request.get('a'), b=request.get('b'), c=request.get('c'))
u = Update(some_params)
u.do_something(thing)
You can add a class method to MyModel
that puts a thing, e.g.:
@classmethod
def put_thing(thing):
model = MyModel(a=thing.a, b=thing.b, c=thing.c)
model.put()
and then your do_something
logic can just call MyModel.put_thing(thing)
if it needs to add it to the database.
Upvotes: 2
Reputation: 69092
handing over the request to the model means you're mixing model and controller.
normaly the model shouldn't even be aware that ther even is a request. geting the parameters from the request is the controller's job, not the models. if your do_something
method has to work with parameters, then it should get them as arguments and return a result (usually an entity).
Upvotes: 4
Reputation: 11706
You can add update as a class method to the MyModel class with a @classmethod decorator and call MyModel.update(a=x)
Upvotes: 1