2017-04-12 151 views
0

我完全是python中的初级编程,我想查看是否有人能够引导我遇到这个问题。在python烧瓶中处理关系

我正在尝试为商店制作一个REST API,并且我被困在关系中。我的问题是,我有以下的终点,模型,服务和每一次我尝试做一个邮寄到API我得到这些错误

AttributeError: "n" is not a valid field for <Specification(id='1', name='Polyester', date_added='2017-04-11 12:39:31.871208')>. 
WARNING:root:(sqlite3.IntegrityError) UNIQUE constraint failed: specification.name [SQL: 'INSERT INTO specification (name, date_added) VALUES (?, ?)'] [parameters: ('Polyester', '2017-04-11 12:39:31.871208')] 

我的产品型号:

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

specification = db.Table('product_specification', db.metadata, 
         db.Column('specification_id', db.Integer, 
            db.ForeignKey('specification.id')), 
         db.Column('product_id', db.Integer, 
            db.ForeignKey('product.id')) 
         ) 


class Product(db.Model): 
    __tablename__ = 'product' 

    id = db.Column(db.Integer, primary_key=True, autoincrement=True) 
    brand = db.Column(db.String(180), nullable=False) 
    description = db.Column(db.String(500), nullable=False) 
    price = db.Column(db.Float) 
    date_added = db.Column(db.DateTime, default=datetime.utcnow()) 

    specification = db.relationship('Specification', secondary=specification, 
            lazy='joined', backref=db.backref('product', lazy='dynamic')) 

    @staticmethod 
    def as_dict(self): 
     return dict(
      brand=self.brand, 
      description=self.description, 
      price=self.price, 
      date_added=self.date_added, 
      specification=self.specification 
     ) 

    def __repr__(self): 
     return "<Products(id='%s', brand='%s', description='%s'," \ 
       "price='%s', date_created='%s'>" % (
        self.id, 
        self.brand, 
        self.description, 
        self.price, 
        self.date_added, 
        self.specification 
       ) 


class ProductSchema(Schema): 
    id = fields.Integer(dump_only=True), 
    brand = fields.String(), 
    description = fields.String(), 
    price = fields.Float(), 
    date_added = fields.DateTime() 
    specification = fields.Nested(SpecificationsSchema) 

    class Meta: 
     type_ = 'product' 
     model = Product, 
     fields = (
      'id', 'brand', 'description', 'price', 'date_added', 'specification' 
     ) 

我规格型号:

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

class Specification(db.Model): 
    __tablename__ = 'specification' 

    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(150), nullable=False, unique=True, index=True) 
    date_added = db.Column(db.DateTime, default=datetime.utcnow()) 

    @staticmethod 
    def as_dict(self): 
     return dict(
      name=self.name, 
     ) 

    def __repr__(self): 
     return "<Specification(id='%s', name='%s', date_added='%s')>" % (
      self.id, 
      self.name, 
      self.date_added, 
     ) 


class SpecificationsSchema(Schema): 
    id = fields.Integer(dump_only=True) 
    name = fields.String() 
    date_added = fields.DateTime() 


    class Meta: 
     type_ = 'specification' 
     model = Specification 
     fields = ('id', 'name', 'date_added') 

我的服务:

#!/usr/bin/python 
# -*- coding: utf-8 -*- 


def add_product(
    brand=None, 
    description=None, 
    price=None, 
    specification=None 
): 

    try: 
     products = Product(
      brand=brand, 
      description=description, 
      price=price, 
      specification=specification 
     ) 

     # Add product object to the db session 
     db.session.add(products) 
     # commit product object to the db session 
     db.session.commit() 
     # return product object status 
     return products 

    except IntegrityError as why: 
     # Logging the error. 
     logging.warning(why) 
     # Return none if there is product unique constraint error. 
     return None 

    except Exception as why: 
     # Logging the error. 
     logging.warning(why) 
     # Return error. 
     return None 

我的观点

#!/usr/bin/python 
# -*- coding: utf-8 -*- 


@api.route('/create/product', methods=['POST']) 
@cross_origin(allow_header=['Content-Type']) 
def create_products(): 
    try: 
     # Get product data 
     json_dict = request.get_json() 
     brand = json_dict['brand'] 
     description = json_dict['description'] 
     price = json_dict['price'] 
     specification = json_dict['specification'] 

    except Exception as why: 
     # Logging the error. 
     logging.warning(why) 

     # Return missed parameter error. 
     return api_response(
      http_code=res.ERROR_999['http_code'], 
      message=res.ERROR_999['message'], 
      code=res.ERROR_999['code'] 
     ) 


    product = add_product(
     brand=brand, 
     description=description, 
     price=price, 
     specification=specification 
    ) 

    # Check if product is already existed. 
    if product is None: 
     return api_response(
      http_code=res.ERROR_409['http_code'], 
      message=res.ERROR_409['message'], 
      code=res.ERROR_409['code'] 
     ) 

    # Products schema for some fields. 
    product_schema = ProductsSchemas(
     only=(
      'id', 
      'brand', 
      'price', 
      'date_added', 
      'specification' 
     )) 

    result = product_schema.dump(product).data 

    return api_response(
     http_code=res.PRODUCT_CREATED_SUCCESSFULLY['http_code'], 
     message=res.PRODUCT_CREATED_SUCCESSFULLY['message'], 
     payload=result 
    ) 

回答

1

specification类型从客户端的请求得到的是str。当调用add_product函数时,将在str类型中使用specification创建Product对象。

但根据您的Product型号,specification是一个外键,它应该是Specification的一个对象。

解决方案

  1. 修复add_product功能,表SpecificationProduct许多一对多的关系。 SQL数据库创建第三个表以实现多对多关系,就像您的product_specification一样。

    因此创建或获取Specification对象,创建一个Product对象,最后添加关系。下面是一个例子,仅供参考:

    def add_product(brand=None, description=None, price=None, specification=None): 
        spec = Specification(name=specification) 
        product = Product(brand=brand, description=description, price=price, specification=spec) 
        product.specification.append(spec) 
        db.session.add_all([spec, product]) 
        db.session.commit() 
    
  2. Ajust你的模型,外键字段更改为串场。它会与项目逻辑发生冲突,并且基本不能解决问题。

+0

感谢@aishenghuomeidaoli 它帮助了我很多,了解他们是如何工作的。 – Fanatic