Работа с отношениями в питоне

Я полностью младший программист на 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 функция, а Product объект будет создан с specification в str тип.

Однако в соответствии с вашим Product модель, specification это внешний ключ, который должен быть объектом Specification,

Решения:

  1. исправлять add_product функция, таблица Specification а также Product отношения многие ко многим. Базы данных 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. Отрегулируйте ваши модели, измените поле внешнего ключа на строковое поле. Это вступит в конфликт с логикой проекта и не решит проблему в принципе.

Другие вопросы по тегам