Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/292.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 一次从网店购买许多产品_Python_Google App Engine_Google Cloud Datastore_Python 2.7_Webshop - Fatal编程技术网

Python 一次从网店购买许多产品

Python 一次从网店购买许多产品,python,google-app-engine,google-cloud-datastore,python-2.7,webshop,Python,Google App Engine,Google Cloud Datastore,Python 2.7,Webshop,通过我的支付系统(api.payson.se)只编写一个产品销售程序非常简单,但同时购买多个不同数量的产品给我带来了麻烦,因为它没有实现,我也不知道如何实现。现在我有了一个解决方案,我刚刚把它放在一起工作,但建模和控制流是一种非常快速和肮脏的,我想知道这是可以接受的,还是需要重写。系统现在可以正常工作,这样我就可以进入商店(步骤1)并输入我想要购买的产品的金额 然后,如果我按Buy(“Köp”)键,我的Python会正确计算总和,无论我所说的总量和产品的组合是什么,这都会起作用,本页还可以列出

通过我的支付系统(api.payson.se)只编写一个产品销售程序非常简单,但同时购买多个不同数量的产品给我带来了麻烦,因为它没有实现,我也不知道如何实现。现在我有了一个解决方案,我刚刚把它放在一起工作,但建模和控制流是一种非常快速和肮脏的,我想知道这是可以接受的,还是需要重写。系统现在可以正常工作,这样我就可以进入商店(步骤1)并输入我想要购买的产品的金额

然后,如果我按Buy(“Köp”)键,我的Python会正确计算总和,无论我所说的总量和产品的组合是什么,这都会起作用,本页还可以列出规范,但尚未实现: 总金额为瑞典货币,且其已向我的数据存储写入状态为“未付”的订单,并包含订购的产品以及数据存储中每个产品的金额: 然后,用户可以取消购买,或继续通过支付系统api.payson.se实际支付: 所以我所需要做的就是倾听Payson的回复,并更新已付款订单的状态。但是我的解决方案看起来不是很干净,我想知道我是否可以继续使用这样的代码,数据模型是两个字符串列表,一个带有数量,一个带有产品(项目ID),因为这是我可以解决它的最简单的方法,但是它不能直接访问,只能从列表中访问。我可以使用更好的数据模型吗

进行处理的代码有点凌乱,可以使用比字符串和列表更好的数据模型和算法:

class ShopHandler(NewBaseHandler):

    @user_required
    def get(self):
        user = \
            auth_models.User.get_by_id(long(self.auth.get_user_by_session()['user_id'
                ]))
        self.render_jinja('shop.htm', items=Item.recent(), user=user)
        return ''

    @user_required
    def post(self, command):
        user = \
            auth_models.User.get_by_id(long(self.auth.get_user_by_session()['user_id'
                ]))
        logging.info('in shophandler http post item id'+self.request.get('item'))

        items = [ self.request.get('items[1]'),self.request.get('items[2]'),self.request.get('items[3]'),self.request.get('items[4]'),self.request.get('items[5]'),self.request.get('items[6]'),self.request.get('items[7]'),self.request.get('items[8]')   ]   

        amounts = [ self.request.get('amounts[1]'),self.request.get('amounts[2]'),self.request.get('amounts[3]'),self.request.get('amounts[4]'),self.request.get('amounts[5]'),self.request.get('amounts[6]'),self.request.get('amounts[7]'),self.request.get('amounts[8]')  ]
        total = 0
        total = int(self.request.get('amounts[1]'))* long(Item.get_by_id(long(self.request.get('items[1]'))).price_fraction()) if self.request.get('amounts[1]') else total
        total = total + int(self.request.get('amounts[2]'))* long(Item.get_by_id(long(self.request.get('items[2]'))).price_fraction()) if self.request.get('amounts[2]') else total
        total = total + int(self.request.get('amounts[3]'))* long(Item.get_by_id(long(self.request.get('items[3]'))).price_fraction()) if self.request.get('amounts[3]') else total
        total = total + int(self.request.get('amounts[4]'))* long(Item.get_by_id(long(self.request.get('items[4]'))).price_fraction()) if self.request.get('amounts[4]') else total
        total = total + int(self.request.get('amounts[5]'))* long(Item.get_by_id(long(self.request.get('items[5]'))).price_fraction()) if self.request.get('amounts[5]') else total
        total = total + int(self.request.get('amounts[6]'))* long(Item.get_by_id(long(self.request.get('items[6]'))).price_fraction()) if self.request.get('amounts[6]') else total
        total = total + int(self.request.get('amounts[7]'))* long(Item.get_by_id(long(self.request.get('items[7]'))).price_fraction()) if self.request.get('amounts[7]') else total
        total = total + int(self.request.get('amounts[8]'))* long(Item.get_by_id(long(self.request.get('items[8]'))).price_fraction()) if self.request.get('amounts[8]') else total
        logging.info('total:'+str(total))
        trimmed = str(total)+',00'
        order = model.Order(status='UNPAID')
        order.items = items
        order.amounts = amounts
        order.put()
        logging.info('order was written')
        ExtraCost = 0
        GuaranteeOffered = 2
        OkUrl = 'http://' + self.request.host + r'/paysonreceive/'
        Key = '3110fb33-6122-4032-b25a-329b430de6b6'
        text = 'niklasro@gmail.com' + ':' + str(trimmed) + ':' + str(ExtraCost) \
            + ':' + OkUrl + ':' + str(GuaranteeOffered) + Key
        m = hashlib.md5()

        BuyerEmail = user.email
        AgentID = 11366
        self.render_jinja('order.htm', order=order, user=user, total=total, Generated_MD5_Hash_Value = hashlib.md5(text).hexdigest(), BuyerEmail=user.email, Description='Bnano Webshop', trimmed=trimmed, OkUrl=OkUrl, BuyerFirstName=user.firstname, BuyerLastName=user.lastname)
我的订单模型是

class Order(db.Model):
  '''a transaction'''
  item = db.ReferenceProperty(Item)
  items = db.StringListProperty()
  amounts = db.StringListProperty()
  owner = db.UserProperty()
  purchaser = db.UserProperty()
  created = db.DateTimeProperty(auto_now_add=True)
  status = db.StringProperty( choices=( 'NEW', 'CREATED', 'ERROR', 'CANCELLED', 'RETURNED', 'COMPLETED', 'UNPAID', 'PAID' ) )
  status_detail = db.StringProperty()
  reference = db.StringProperty()
  secret = db.StringProperty() # to verify return_url
  debug_request = db.TextProperty()
  debug_response = db.TextProperty()
  paykey = db.StringProperty()
  shipping = db.TextProperty()
产品的型号(即项目)为

class Item(db.Model):
  '''an item for sale'''
  owner = db.UserProperty() #optional
  created = db.DateTimeProperty(auto_now_add=True)
  title = db.StringProperty(required=True)
  price = db.IntegerProperty() # cents / fractions, use price_decimal to get price in dollar / wholes
  image = db.BlobProperty()
  enabled = db.BooleanProperty(default=True)
  silver = db.IntegerProperty() #number of silver

  def price_dollars( self ):
    return self.price / 100.0

  def price_fraction( self ):
    return self.price / 100.0

  def price_silver( self ): #number of silvers an item "is worth"
    return self.silver / 1000.000

  def price_decimal( self ):
    return decimal.Decimal( str( self.price / 100.0 ) )

  def price_display( self ):
    return str(self.price_fraction()).replace('.',',')

  @staticmethod
  def recent():
    return Item.all().filter( "enabled =", True ).order('-created').fetch(10)
我想你现在已经知道发生了什么,这种方法对用户有效,但是代码看起来不太好。你认为我可以这样离开代码,继续保持这个“解决方案”吗?还是我必须重写以使它更合适?商店里只有8种产品,使用此解决方案,很难添加新的销售项目,因为那时我必须重新编程脚本,这并不完美

你能评论一下或者回答一下吗?我很高兴能得到一些关于这个快速而肮脏的用例解决方案的反馈

多谢各位

更新 我做了一次重写,以允许添加新产品,以下内容似乎比以前更好:

class ShopHandler(NewBaseHandler):

    @user_required
    def get(self):
        user = \
            auth_models.User.get_by_id(long(self.auth.get_user_by_session()['user_id'
                ]))
        self.render_jinja('shop.htm', items=Item.recent(), user=user)
        return ''

    @user_required
    def post(self, command):
        user = \
            auth_models.User.get_by_id(long(self.auth.get_user_by_session()['user_id'
                ]))
        logging.info('in shophandler http post')

        total = 0
        order = model.Order(status='UNPAID')

        for item in self.request.POST:
            amount = self.request.POST[item]
            logging.info('item:'+str(item))
            purchase = Item.get_by_id(long(item))
            order.items.append(purchase.key())
            order.amounts.append(int(amount))
            order.put()
            price = purchase.price_fraction()
            logging.info('amount:'+str(amount))
            logging.info('product price:'+str(price))
            total = total + price*int(amount)

        logging.info('total:'+str(total))
        order.total = str(total)
        order.put()
        trimmed = str(total).replace('.',',') + '0'
        ExtraCost = 0
        GuaranteeOffered = 2
        OkUrl = 'http://' + self.request.host + r'/paysonreceive/'
        Key = '6230fb54-7842-3456-b43a-349b340de3b8'
        text = 'niklasro@gmail.com' + ':' + str(trimmed) + ':' \
            + str(ExtraCost) + ':' + OkUrl + ':' \
            + str(GuaranteeOffered) + Key
        m = hashlib.md5()
        BuyerEmail = user.email  # if user.email else user.auth_id[0]
        AgentID = 11366
        self.render_jinja(
            'order.htm',
            order=order,
            user=user,
            total=total,
            Generated_MD5_Hash_Value=hashlib.md5(text).hexdigest(),
            BuyerEmail=user.email,
            Description='Bnano Webshop',
            trimmed=trimmed,
            OkUrl=OkUrl,
            BuyerFirstName=user.firstname,
            BuyerLastName=user.lastname,
            )

伙计,这真是个奇怪的密码。如果你想在你的商店里添加新的物品,你必须重写你的商店脚本。 在第一次从接口取消项目链接时,您必须向控制器发送带有项目ID和数量的POST请求,我不知道gae请求对象是如何工作的,但它必须是这样的: 从您的订单页面发出POST请求,其中包含真正需要{“item_id”:“qnt”}的物品。 在控制器中,您可以获取所有对象,如:

for item, qnt in request.POST:
    {do something with each item, for example where you can sum total}
等等
不要直接将控制器与接口链接。若你们想制作一个真正灵活的应用程序,你们必须编写更多的抽象代码

我将试着关注您的代码中一个非常明显的问题,但其中有很多问题我不打算深入讨论。我的建议是马上停止。您正在实施基于web的支付系统。你真的应该把它留给那些有更多技能和经验的人。“基于网络的”在确保安全性的同时很难做到正确,但在线支付系统是一种薪酬丰厚、拥有数十年经验的咨询师所能做到的,而且他们仍然经常出错。你要承担很多法律责任

如果你还执著于此,请从头读到尾,可能会读几遍。Python是一种非常不同的语言,与您在脑海中死记硬背的任何经典OOP语言都不同。之后,至少浏览一下其他文档。如果您在这些方面遇到了问题,请拿起一本关于Python的O'Reilly书;从另一个角度来看应该会有所帮助。在您完成所有这些之后(可能同时),编写尽可能多的代码,如果您做错了,这些代码不会让您被遗忘。然后也许你可以写一个订单/付款系统

如果这听起来很苛刻,我很抱歉,但是这个世界不需要更多的劣质网络商店;1999年为我们解决了这个问题

无论如何,当您编写重复的内容并复制粘贴时,请转到您的代码:D,如下所示:

items = [ self.request.get('items[1]'),self.request.get('items[2]'),self.request.get('items[3]'),self.request.get('items[4]'),self.request.get('items[5]'),self.request.get('items[6]'),self.request.get('items[7]'),self.request.get('items[8]')   ]
items = []
i = 0
while True:
    try:
        items.append(self.request[i + 1]) #attempt to get the next item
    except IndexError as exc: #but if it fails...
        break #we must be at the last one
    i += 1
你应该想一想,“等一下!重复的任务正是计算机设计的目的。”你可以让你的文本编辑器来做这件事(见Vim宏),但简洁(但不要太简洁;)的代码总是比长代码好,因为你可以使它更快地维护,更少地发生程序员错误,更容易调试,更不用说不复制和粘贴节省的时间了,所以让我们改进代码

下面是我将如何在Python中修改这一点(高级程序员会在他们的头脑中进行修改,或者直接跳到最后):

实际上,限制物品的数量是相当业余的,只会让你的用户感到沮丧。您可以这样修复它:

items = [ self.request.get('items[1]'),self.request.get('items[2]'),self.request.get('items[3]'),self.request.get('items[4]'),self.request.get('items[5]'),self.request.get('items[6]'),self.request.get('items[7]'),self.request.get('items[8]')   ]
items = []
i = 0
while True:
    try:
        items.append(self.request[i + 1]) #attempt to get the next item
    except IndexError as exc: #but if it fails...
        break #we must be at the last one
    i += 1
我认为这是你现在应该采用的方式,因为它很清楚,但不重复。但是,您可以使用中的函数进一步缩短它

一些快速提示:

  • 避免字符串连接,尤其是在用户提供字符串的情况下,尤其是涉及到用户通过web提供的字符串时。使用str.format和模字符串格式。奖励:您不必将所有内容都转换为字符串
  • 从中间取出这些常量(例如,
    ExtraCost=2
    ),并将它们放在安全的地方(在模块的顶部,或包中的特殊文件中)
  • 你太信任用户了