I'm new to Odoo (openERP) and python. I have an http.Controller in which I'm trying to retrieve a template which should contain some objects from openERP database, more specifically fleet_vehicle_log_fuel_obj.
Usually the self.pool.get() method should do the trick, but in controller it doesn't work.
I'm trying to send some objects to the client and process them with javascript.
Here's my controller:
import json
from openerp import SUPERUSER_ID, pooler
from openerp.addons.web import http
from openerp.addons.web.http import request
class google_map(http.Controller):
#http.route(['/google_map'], type='http', auth="public", website=True)
def google_map(self, *arg, **post):
cr, uid, context = request.cr, request.uid, request.context
fleet_vehicle_log_fuel_obj = self.pool.get('fleet_vehicle_log_fuel');
#fleet_vehicle_log_fuel_obj = pool.get('fleet_vehicle_log_fuel')
ids = fleet_vehicle_log_fuel_obj.search(cr, uid, [])
return request.website.render("fleet.google_map", json.dumps(ids))
the error I get is 'google_map' object has no attribute 'pool'. How can i get all the objects of a certain type and send them to the client?
I know I have arrived too late, but may be this helps to someone.
The http library allows you to access the models from the controller, so you should write:
import openerp.http as http
fleet_vehicle_log_fuel_obj = http.request.env['fleet_vehicle_log_fuel']
And then you will be able to apply any ORM method with fleet_vehicle_log_fuel_obj.
Try this:
pool = request.registry
model_obj = pool['your.model']
or
model_obj = request.registry['your.model']
Hope this will help you...
I haven't tested this but try add to import:
import openerp.pooler as pooler
Then use the code
osv_pool = pooler.get_pool(dbname)
osv_pool.get(model)
I got this from openerp/osv/osv.py
Related
I want to test my tornado python application with pytest.
for that purpose, I want to have a mock db for the mongo and to use motor "fake" client to simulate the calls to the mongodb.
I found alot of solution for pymongo but not for motor.
any idea?
I do not clearly understand your problem — why not just have hard-coded JSON data?
If you just want to have a class that would mock the following:
from motor.motor_tornado import MotorClient
client = MotorClient(MONGODB_URL)
my_db = client.my_db
result = await my_db['my_collection'].insert_one(my_json_load)
So I recommend creating a Class:
Class Collection():
database = []
async def insert_one(self,data):
database.append(data)
data['_id'] = "5063114bd386d8fadbd6b004" ## You may make it random or consequent
...
## Also, you may save the 'database' list to the pickle on disk to preserve data between runs
return data
async def find_one(self, data):
## Search in the list
return data
async def delete_one(self, data_id):
delete_one.deleted_count = 1
return
## Then create a collection:
my_db = {}
my_db['my_collecton'] = Collection()
### The following is the part of 'views.py'
from tornado.web import RequestHandler, authenticated
from tornado.escape import xhtml_escape
class UserHandler(RequestHandler):
async def post(self, name):
getusername = xhtml_escape(self.get_argument("user_variable"))
my_json_load = {'username':getusername}
result = await my_db['my_collection'].insert_one(my_json_load)
...
return self.write(result)
If you would clarify your question, I will develop my answer.
I'm using twisted as a FTP Server:
from twisted.protocols.ftp import FTPFactory, FTPRealm
from twisted.cred.portal import Portal
from twisted.cred.checkers import AllowAnonymousAccess, FilePasswordDB
from twisted.internet import reactor
p = Portal(FTPRealm('./'),
[AllowAnonymousAccess(), FilePasswordDB("pass.dat")])
f = FTPFactory(p)
reactor.listenTCP(21, f)
reactor.run()
How can i log every received FTP command from client?
FTPRealm creates FTPAnonymousShell and FTPShell instances (avatars) to mediate access to the filesystem.
These classes both implement IFTPShell. One solution is to create a wrapper for FTPRealm which applies a logging wrapper to the avatars it creates.
from twisted.python.components import proxyForInterface
class WrappingRealm(proxyForInterface(IRealm)):
wrap = staticmethod(logging_wrapper)
def requestAvatar(self, *a, **kw):
d = maybeDeferred(
super(WrappingRealm, self).requestAvatar,
*a, **kw
)
def got_avatar((iface, avatar, logout)):
return (iface, self.wrap(avatar), logout)
d.addCallback(got_avatar)
return d
And implement logging_wrapper something like:
class _LoggingFTPShell(proxyForInterface(IFTPShell)):
def makeDirectory(self, path):
log(avatar=self.avatar, operation="makeDirectory", path=path)
return super(_LoggingFTPShell, self).makeDirectory(path)
# The same for the rest of the methods of IFTPShell
# ...
def logging_wrapper(avatar):
return _LoggingFTPShell(avatar)
This is a bit tedious since you have to add logging for each method on the interface. However, since Twisted's FTP protocol implementation doesn't natively provide facilities for performing the logging you want, it's hard to get around this. With some meta-programming you might save yourself some typing (but at the cost of some complexity).
Another approach would be to contribute a patch to Twisted adding the logging you're interested in.
Below I provided a code example which simply respond to HTTP GET request with the data from Redis:
Request: http://example.com:8888/?auth=zefDWDd5mS7mcbfoDbDDf4eVAKb1nlDmzLwcmhDOeUc
Response: get: u'"True"'
The purpose of this code is to serve as a REST server (that's why I'm using lazyConnectionPool) responding to the requests, and using data from Redis (read/ write).
What I need to do:
Run multiple requests to Redis inside render_GET of the IndexHandler (like GET, HMGET, SET, etc)
Run multiple requests in a transaction inside render_GET of the IndexHandler
I've tried multiple ways to do that (including examples from the txredisapi library), but due to lack of experience failed to do that. Could you please advise on questions 1) and 2).
Thanks in advance.
import txredisapi as redis
from twisted.application import internet
from twisted.application import service
from twisted.web import server
from twisted.web.resource import Resource
class Root(Resource):
isLeaf = False
class BaseHandler(object):
isLeaf = True
def __init__(self, db):
self.db = db
Resource.__init__(self)
class IndexHandler(BaseHandler, Resource):
def _success(self, value, request, message):
request.write(message % repr(value))
request.finish()
def _failure(self, error, request, message):
request.write(message % str(error))
request.finish()
def render_GET(self, request):
try:
auth = request.args["auth"][0]
except:
request.setResponseCode(404, "not found")
return ""
d = self.db.hget(auth, 'user_add')
d.addCallback(self._success, request, "get: %s\n")
d.addErrback(self._failure, request, "get failed: %s\n")
return server.NOT_DONE_YET
# Redis connection parameters
REDIS_HOST = '10.10.0.110'
REDIS_PORT = 6379
REDIS_DB = 1
REDIS_POOL_SIZE = 1
REDIS_RECONNECT = True
# redis connection
_db = redis.lazyConnectionPool(REDIS_HOST, REDIS_PORT, REDIS_DB, REDIS_POOL_SIZE)
# http resources
root = Root()
root.putChild("", IndexHandler(_db))
application = service.Application("web")
srv = internet.TCPServer(8888, server.Site(root), interface="127.0.0.1")
srv.setServiceParent(application)
Regarding first question:
There is a few ways to generalize to making multiple database requests in a single HTTP request.
For example you can make multiple requests:
d1 = self.db.hget(auth, 'user_add')
d2 = self.db.get('foo')
Then you can get a callback to trigger when all of these simultaneous requests are finished (see twisted.internet.defer.DeferredList).
Or you can use inlineCallbacks if you need sequential requests. For example:
#inlineCallbacks
def do_redis(self):
foo = yield self.db.get('somekey')
bar = yield self.db.hget(foo, 'bar') # Get 'bar' field of hash foo
But you will need to read more about combining inlineCallbacks with twisted.web (there are SO questions on that topic you should look up).
Regarding question 2:
Transactions are really ugly to do without using inlineCallbacks. There is an example at txredisapi homepage that shows it using inlineCallbacks.
from suds.client import Client ##UnresolvedImport
from suds.transport.https import HttpAuthenticated ##UnresolvedImport
import urllib2
class methodinvokeclass():
def methodinvokemethod(self,*args):
method=args[1]
c=args[2]
print c
response=c.service.method("90210")# I know this wont work,coz of method, but even I cant get me way thru with getattr
#response=c.service.LatLonListZipCode("90210")
print response
if __name__=="__main__":
invokemethodname="LatLonListZipCode"#Webservice name which I want to invoke...later !
f=open("C:\wsdllocation.txt",'r')# picks up the WSDL file location from the above file
webservwsdl=f.readline()
f.close()
y=methodinvokeclass()#dummy object
z=methodinvokeclass()#dummy object
t = HttpAuthenticated(username='x', password='x')#helps me getting thru my corporate firewall
t.handler = urllib2.HTTPBasicAuthHandler(t.pm)#helps me getting thru my corporate firewall
t.urlopener = urllib2.build_opener(t.handler)#helps me getting thru my corporate firewall
c = Client(url=webservwsdl,transport=t)#SUDs client !!!!!
x=y.methodinvokemethod(z,invokemethodname,c)# invoking the code above
You can use getattr to retrieve the SOAP method from the service. Use this instead:
impl = getattr(c.service, method)
response = impl('90210')
print response
Here is a working example, using a webservicex test SOAP service:
url = 'http://www.webservicex.net/stockquote.asmx?WSDL'
client = Client(url=url)
name = 'GetQuote'
impl = getattr(client.service, name)
print impl('IBM')
Output:
<StockQuotes>
<Stock>
<Symbol>IBM</Symbol>
<Last>163.81</Last>
<Date>4/7/2011</Date>
<Time>11:47am</Time>
<Change>-0.23</Change>
<Open>164.10</Open>
<High>164.5463</High>
<Low>163.44</Low>
<Volume>1573461</Volume>
<MktCap>199.8B</MktCap>
<PreviousClose>164.04</PreviousClose>
<PercentageChange>-0.14%</PercentageChange>
<AnnRange>116.00 - 167.72</AnnRange>
<Earns>11.52</Earns>
<P-E>14.24</P-E>
<Name>International Bus</Name>
</Stock>
</StockQuotes>
I'm trying to use Pylons with SqlAlchemy (through Elixir).
Here is my testdb/model/entities.py:
from elixir import *
metadata.bind = "mysql://testdb:hundertwasser#localhost/testdb"
metadata.bind.echo = True
class Post(Entity):
text = Field(Unicode(128))
And here is the controller:
import logging
from pylons import request, response, session, tmpl_context as c, url
from pylons.controllers.util import abort, redirect
from testdb.lib.base import BaseController, render
log = logging.getLogger(__name__)
from testdb.model.entities import *
class MainController(BaseController):
def index(self):
c.posts = Post.query.all()
print "Test"
return render('/index.mako')
def submit(self):
post = Post()
post.text = request.POST.get['text']
session.commit()
When I run the application, I get an error saying:
AttributeError: type object 'Post' has no attribute 'query'
Does someone know what I'm doing wrong?
The answer is as follows:
entities.py is missing the following two lines at the bottom:
setup_all()
create_all()
I don't know Elixir well, but isn't putting the following in the .ini enough?
sqlalchemy.url = mysql://user:pass#localhost/dbname?charset=utf8&use_unicode=0
sqlalchemy.pool_recycle = 3600
All the stuff after ? is to avoid encoding problems. The second line prevents MySQL from closing inactive connections (in fact it reconnects every hour).