开发者

Alternative to singleton?

I'm a Python & App Engine (and server-side!) newbie, and I'm trying to create very simple CMS. Each deployment of the application would have one -and only one -company object, instantiated from something like:

class Company(db.Model):
    name = db.StringPropery()
    profile = db.TextProperty()
    addr = db.TextProperty() 

I'm trying to provide the facility to update the company profile and other details.

My first thought was to have a Company entity singleton. But having looked at (although far from totally grasped) this thread I get the impression that it's difficult, and inadvisable, to do this.

So then I thought that perhaps for each deployment of the CMS I could, as a one-off, run a script (triggered by a totally obscure URL) which simply instantiates Company. From then on, I would get this instance with theCompany = Company.all()[0]

Is this advisable?

Then I remembered that someone in that thread suggested simply using a module. So I just created a Company.py file and stuck a few variables in it. I've tried this in the SDK and it seems to work -to my s开发者_JAVA技巧uprise, modified variable values "survived" between requests.

Forgive my ignorance but, I assume these values are only held in memory rather than on disk -unlike Datastore stuff? Is this a robust solution? (And would the module variables be in scope for all invocations of my application's scripts?)


Global variables are "app-cached." This means that each particular instance of your app will remember these variables' values between requests. However, when an instance is shutdown these values will be lost. Thus I do not think you really want to store these values in module-level variables (unless they are constants which do not need to be updated).

I think your original solution will work fine. You could even create the original entity using the remote API tool so that you don't need an obscure page to instantiate the one and only Company object.

You can also make the retrieval of the singleton Company entity a bit faster if you retrieve it by key.

If you will need to retrieve this entity frequently, then you can avoid round-trips to the datastore by using a caching technique. The fastest would be to app-cache the Company entity after you've retrieved it from the datastore. To protect against the entity from becoming too out of date, you can also app-cache the time you last retrieved the entity and if that time is more than N seconds old then you could re-fetch it from the datastore. For more details on this option and how it compares to alternatives, check out Nick Johnson's article Storage options on App Engine.


It sounds like you are trying to provide a way for your app to be configurable on a per-application basis.

Why not use the datastore to store your company entity with a key_name? Then you will always know how to fetch the company entity, and you'll be able edit the company without redeploying.

company = Company(key_name='c')
# set stuff on company....
company.put()

# later in code...
company = Company.get_by_key_name('c')

Use memcache to store the details of the company and avoid repeated datastore calls.

In addition to memcache, you can use module variables to cache the values. They are cached, as you have seen, between requests.


I think the approach you read about is the simplest:

  • Use module variables, initialized in None.
  • Provide accessors (get/setters) for these variables.
  • When a variable is accessed, if its value is None, fetch it from the database. Otherwise, just use it.

This way, you'll have app-wide variables provided by the module (which won't be instantiated again and again), they will be shared and you won't lose them.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜