2017-04-12 95 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