在使用SQL Alchemy ORM的python中,尝试更新数据库中的记录

时间:2016-03-29 20:15:04

标签: python sql sqlalchemy int

我正在尝试更新数据库中的餐馆名称并收到错误。

网站打印出所有餐馆名称,然后用户在餐厅下面选择“编辑”按钮,他们想要更改名称。在转到另一个页面之前,我使用餐馆名称查询数据库,检索id,然后我构建将PK插入URL。

然后我分解URL并在POST方法中检索PK并尝试使用用户选择的名称更新数据库名称。

以下是代码和当前错误:

webserver.py

from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from database_setup import Restaurant, Base, MenuItem
import cgi

class webServerHandler(BaseHTTPRequestHandler):

    def do_GET(self):
        try:
            if self.path.endswith("/hello"):
                self.send_response(200)
                self.send_header('Content-type', 'text/html')
                self.end_headers()
                output = ""
                output += "<html><body>Hello!"
                output += '''<form method='POST' enctype='multipart/form-data' action='/hello'><h2>What would you like me to say?</h2><input name="message" type="text" ><input type="submit" value="Submit"> </form>'''
                output +="</body></html>"
                self.wfile.write(output)
                print output
                return

            if self.path.endswith("/hola"):
                self.send_response(200)
                self.send_header('Content-type', 'text/html')
                self.end_headers()
                output = ""
                output += "<html><body> &#161 Hola ! <a href = '/hello'> Back to Hello </a></body></html>"
                output += '''<form method='POST' enctype='multipart/form-data' action='/hello'><h2>What would you like me to say?</h2><input name="message" type="text" ><input type="submit" value="Submit"> </form>'''
                output +="</body></html>"
                self.wfile.write(output)
                print message
                return

            if self.path.endswith("/restaurants"):
                self.send_response(200)
                self.send_header('Content-type', 'text/html')
                self.end_headers()
                engine = create_engine('sqlite:///restaurantmenu.db')
                Base.metadata.bind = engine
                DBSession = sessionmaker(bind = engine)
                session = DBSession()
                items = session.query(Restaurant).all()
                output = "<html><body> <br> Printing all Restaurants ! </br>"
                for item in items:
                    output += "<br>" + item.name + "</br>"
                    output += "<br> <a href = '/" + str(item.id) + "/rename'> Edit </a></br>"
                    output += "<br> <a href = '/" + str(item.id) + "/delete'> Delete </a></br>"
                output += "<br> <a href = '/new'> Create new restaurant </a></br>"
                output += "</body></html>"
                self.wfile.write(output)
                print output
                return

            if self.path.endswith("/new"):
                self.send_response(200)
                self.send_header('Content-type', 'text/html')
                self.end_headers()
                output = ""
                output += "<html><body>Make a New Restaurant"
                output += '''<form method='POST' enctype='multipart/form-data' action='/new'><h2>Name of new restaurant ?</h2><input name="message" type="text" ><input type="submit" value="Submit"> </form>'''
                output +="</body></html>"
                self.wfile.write(output)
                print output
                return

            if self.path.endswith("/rename"):
                self.send_response(200)
                self.send_header('Content-type', 'text/html')
                self.end_headers()
                x = self.path
                x = x[:-7]
                x = x[1:]
                engine = create_engine('sqlite:///restaurantmenu.db')
                Base.metadata.bind = engine
                DBSession = sessionmaker(bind = engine)
                session = DBSession()
                items = session.query(Restaurant).filter_by(id = x)
                output = ""
                for item in items:
                    output += "<html><body><h2>" + item.name + "</h2>"
                output += '''<form method='POST' enctype='multipart/form-data' action='/rename'><h2>New name of restaurant ?</h2><input name="message" type="text" ><input type="submit" value="Submit"> </form>'''
                output +="</body></html>"
                self.wfile.write(output)
                print output
                print x
                return

        except IOError:
            self.send_error(404, 'File Not Found: %s' % self.path)

    def do_POST(self):
        if self.path.endswith("/new"):
            self.send_response(301)
            self.send_header('Content-type','text/html')
            self.end_headers()
            ctype, pdict = cgi.parse_header(
            self.headers.getheader('content-type'))
            if ctype == 'multipart/form-data':
                fields = cgi.parse_multipart(self.rfile, pdict)
                messagecontent = fields.get('message')
            engine = create_engine('sqlite:///restaurantmenu.db')
            Base.metadata.bind = engine
            DBSession = sessionmaker(bind = engine)
            session = DBSession()
            myrest = Restaurant(name = messagecontent[0])
            session.add(myrest)
            session.commit()
            output = "Restaurant added"
            output +="<br><a href = '/restaurants'> Back to restaurants </a></br>"
            output +="</body></html>"
            self.wfile.write(output)
            print output

        if self.path.endswith("/rename"):
            self.send_response(301)
            self.send_header('Content-type','text/html')
            self.end_headers()
            y = self.path
            y = y[:-7]
            y = y[1:]
            print y
            ctype, pdict = cgi.parse_header(
            self.headers.getheader('content-type'))
            if ctype == 'multipart/form-data':
                fields = cgi.parse_multipart(self.rfile, pdict)
                messagecontent = fields.get('message')
            engine = create_engine('sqlite:///restaurantmenu.db')
            Base.metadata.bind = engine
            DBSession = sessionmaker(bind = engine)
            session = DBSession()
            findrest = session.query(Restaurant).filter_by(id = y).one()
            findrest.name = messagecontent[0]
            session.add(findrest)
            session.commit()
            output = "Restaurant " + messagecontent[0] + " added"
            output +="<br><a href = '/restaurants'> Back to restaurants </a></br>"
            output +="</body></html>"
            self.wfile.write(output)
            print output

def main():
    try:
        port = 8080
        server = HTTPServer(('', port), webServerHandler)
        print "Web Server running on port %s" % port
        server.serve_forever()
    except KeyboardInterrupt:
        print " ^C entered, stopping web server...."
        server.socket.close()

if __name__ == '__main__':
    main()

database_setup.py

import os
import sys
from sqlalchemy import Column, ForeignKey, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
from sqlalchemy import create_engine

Base = declarative_base()


class Restaurant(Base):
    __tablename__ = 'restaurant'

    id = Column(Integer, primary_key=True)
    name = Column(String(250), nullable=False)


class MenuItem(Base):
    __tablename__ = 'menu_item'

    name = Column(String(80), nullable=False)
    id = Column(Integer, primary_key=True)
    description = Column(String(250))
    price = Column(String(8))
    course = Column(String(250))
    restaurant_id = Column(Integer, ForeignKey('restaurant.id'))
    restaurant = relationship(Restaurant)


engine = create_engine('sqlite:///restaurantmenu.db')


Base.metadata.create_all(engine)
来自网络服务器的

错误

1
10.0.2.2 - - [30/Mar/2016 10:10:46] "POST /rename HTTP/1.1" 301 -

----------------------------------------
Exception happened during processing of request from ('10.0.2.2', 59743)
Traceback (most recent call last):
  File "/usr/lib/python2.7/SocketServer.py", line 295, in _handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 321, in process_request
    self.finish_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 334, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib/python2.7/SocketServer.py", line 649, in __init__
    self.handle()
  File "/usr/lib/python2.7/BaseHTTPServer.py", line 340, in handle
    self.handle_one_request()
  File "/usr/lib/python2.7/BaseHTTPServer.py", line 328, in handle_one_request
    method()
  File "webserver.py", line 132, in do_POST
    findrest = session.query(Restaurant).filter_by(id = int(y)).one()
ValueError: invalid literal for int() with base 10: ''
----------------------------------------

您可以看到Y在上面的

中打印为1

2 个答案:

答案 0 :(得分:0)

您遇到了命名空间问题。

do_GET()方法中定义的变量在do_POST()中不可见,并且完全正常。

如果您想在两者之间分享内容,请使用x = self.path替换self.x = self.path来使用类属性。
因此,如果您想在do_POST中访问它,findrest = session.query(Restaurant).filter_by(id = self.x).one()应该有效。

最后的注意事项:如果您只是在玩BaseHTTPRequestHandler来理解它很好。否则,你可以看看Flask或Django!

答案 1 :(得分:0)

解决!解决方案代码如下:

webserver.py

from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from database_setup import Restaurant, Base, MenuItem
import cgi

class webServerHandler(BaseHTTPRequestHandler):

    def do_GET(self):
        try:
            if self.path.endswith("/hello"):
                self.send_response(200)
                self.send_header('Content-type', 'text/html')
                self.end_headers()
                output = ""
                output += "<html><body>Hello!"
                output += '''<form method='POST' enctype='multipart/form-data' action='/hello'><h2>What would you like me to say?</h2><input name="message" type="text" ><input type="submit" value="Submit"> </form>'''
                output +="</body></html>"
                self.wfile.write(output)
                print output
                return

            if self.path.endswith("/hola"):
                self.send_response(200)
                self.send_header('Content-type', 'text/html')
                self.end_headers()
                output = ""
                output += "<html><body> &#161 Hola ! <a href = '/hello'> Back to Hello </a></body></html>"
                output += '''<form method='POST' enctype='multipart/form-data' action='/hello'><h2>What would you like me to say?</h2><input name="message" type="text" ><input type="submit" value="Submit"> </form>'''
                output +="</body></html>"
                self.wfile.write(output)
                print message
                return

            if self.path.endswith("/restaurants"):
                self.send_response(200)
                self.send_header('Content-type', 'text/html')
                self.end_headers()
                engine = create_engine('sqlite:///restaurantmenu.db')
                Base.metadata.bind = engine
                DBSession = sessionmaker(bind = engine)
                session = DBSession()
                items = session.query(Restaurant).all()
                output = "<html><body> <br> Printing all Restaurants ! </br>"
                for item in items:
                    output += "<br>" + item.name + "</br>"
                    output += "<br> <a href = '/" + str(item.id) + "/rename'> Edit </a></br>"
                    output += "<br> <a href = '/" + str(item.id) + "/delete'> Delete </a></br>"
                output += "<br> <a href = '/new'> Create new restaurant </a></br>"
                output += "</body></html>"
                self.wfile.write(output)
                print output
                return

            if self.path.endswith("/new"):
                self.send_response(200)
                self.send_header('Content-type', 'text/html')
                self.end_headers()
                output = ""
                output += "<html><body>Make a New Restaurant"
                output += '''<form method='POST' enctype='multipart/form-data' action='/new'><h2>Name of new restaurant ?</h2><input name="message" type="text" ><input type="submit" value="Submit"> </form>'''
                output +="</body></html>"
                self.wfile.write(output)
                print output
                return

            if self.path.endswith("/rename"):
                self.send_response(200)
                self.send_header('Content-type', 'text/html')
                self.end_headers()
                engine = create_engine('sqlite:///restaurantmenu.db')
                Base.metadata.bind = engine
                DBSession = sessionmaker(bind = engine)
                session = DBSession()
                x = self.path
                x = x[:-7]
                x = x[1:]
                item = session.query(Restaurant).filter_by(id = x).one()
                output = ""
                output += "<html><body><h2>" + item.name + "</h2>"
                output += """<form method='POST' enctype='multipart/form-data' action='/""" + str(item.id) + """/rename'><h2>New name of restaurant ?</h2><input name="message" type="text" ><input type="submit" value="Submit"> </form>"""
                output +="</body></html>"
                self.wfile.write(output)
                print output
                return

        except IOError:
            self.send_error(404, 'File Not Found: %s' % self.path)

    def do_POST(self):
        if self.path.endswith("/new"):
            self.send_response(301)
            self.send_header('Content-type','text/html')
            self.end_headers()
            ctype, pdict = cgi.parse_header(
            self.headers.getheader('content-type'))
            if ctype == 'multipart/form-data':
                fields = cgi.parse_multipart(self.rfile, pdict)
                messagecontent = fields.get('message')
            engine = create_engine('sqlite:///restaurantmenu.db')
            Base.metadata.bind = engine
            DBSession = sessionmaker(bind = engine)
            session = DBSession()
            myrest = Restaurant(name = messagecontent[0])
            session.add(myrest)
            session.commit()
            output = "Restaurant added"
            output +="<br><a href = '/restaurants'> Back to restaurants </a></br>"
            output +="</body></html>"
            self.wfile.write(output)
            print output

        if self.path.endswith("/rename"):
            self.send_response(301)
            self.send_header('Content-type','text/html')
            self.end_headers()
            y = self.path
            y = y[:-7]
            y = y[1:]
            ctype, pdict = cgi.parse_header(
            self.headers.getheader('content-type'))
            if ctype == 'multipart/form-data':
                fields = cgi.parse_multipart(self.rfile, pdict)
                messagecontent = fields.get('message')
            engine = create_engine('sqlite:///restaurantmenu.db')
            Base.metadata.bind = engine
            DBSession = sessionmaker(bind = engine)
            session = DBSession()
            findrest = session.query(Restaurant).filter_by(id = y).one()
            findrest.name = messagecontent[0]
            session.add(findrest)
            session.commit()
            output = "Restaurant " + messagecontent[0] + " renamed"
            output +="<br><a href = '/restaurants'> Back to restaurants </a></br>"
            output +="</body></html>"
            self.wfile.write(output)
            print output

def main():
    try:
        port = 8080
        server = HTTPServer(('', port), webServerHandler)
        print "Web Server running on port %s" % port
        server.serve_forever()
    except KeyboardInterrupt:
        print " ^C entered, stopping web server...."
        server.socket.close()

if __name__ == '__main__':
    main()