Запрос ввода Flask sqlalchemy, как запрашивать два динамических идентификатора внешнего ключа из таблицы отношений

#python #postgresql #flask #sqlalchemy

#python #postgresql #flask #sqlalchemy

Вопрос:

Я пытаюсь обновить данные во внешнем интерфейсе, используя React / Redux из запроса PUT в серверной части flask / sqlalchemy / postgres. Моя проблема в том, что моя конечная точка может обновляться только по идентификатору, который бесполезен для интерфейса. Причина в том, что обновляемые данные взяты из класса отношений, который существует только для объединения двух других классов. Что мне нужно сделать, так это выяснить, как запрашивать и возвращать user_id и country_id, а не id . Кстати, я тестирую локально с помощью Postman. Модели для класса соединения (таблицы) следующие

 class users_countries_join(db.Model):
    id = db.Column(Integer, autoincrement=True, primary_key=True)
    user_id = db.Column(Integer, ForeignKey(users.id), nullable=False)
    country_id = db.Column(Integer, ForeignKey(countries.id), nullable=False)
    status = db.Column(Integer, nullable=False)
    notes = db.Column(TEXT, nullable=True)
    user = db.relationship('users', backref='user_countries')
    country = db.relationship('countries', backref='travelers')

    def __init__(self, user_id, country_id, status, notes):
        self.user_id = user_id
        self.country_id = country_id
        self.status = status
        self.notes = notes

    def __repr__(self):
        return '<{}>' % self.__name__
  

Код для конечной точки:

 @app.route('/api/mapview/<int:user_id>/<int:country_id>/<int:id>', methods=['PUT'])
def update_mapView_data(user_id, country_id, id):
   user_country = users_countries_join.query.get(id)
   user_country.user_id = request.json[‘user_id’]
   user_country.country_id = request.json[‘country_id’]
   user_country.status = request.json[‘status’]
   user_country.notes = request.json[‘notes’]
    db.session.commit()
    return user_country_schema.jsonify(user_country)
  

Я пытался изменить конечную точку на приведенный ниже код, но это не работает. Теоретически, это то обновление, которое мне нужно. Тот, который обновляется путем доступа к данным через user_id и country_id, а не идентификатор класса. Я начинаю думать, что идентификатор не нужен для начала.

 @app.route('/api/mapview/<int:user_id>/<int:country_id>', methods=['PUT'])
def update_mapView_data(user_id, country_id):
   user_country = users_countries_join.query.get(user_id, country_id)
   user_country.user_id = request.json[‘user_id’]
   user_country.country_id = request.json[‘country_id’]
   user_country.status = request.json[‘status’]
   user_country.notes = request.json[‘notes’]
    db.session.commit()
    return user_country_schema.jsonify(user_country)
  

Может кто-нибудь указать мне правильное направление в том, как это сделать? Я надеюсь, что я просто усложняю это, чем это должно быть.

Комментарии:

1. В вашем случае я считаю, что SQLAlchemy. Больше подходит таблица, а не SQLAlchemy. Модель для users_countries_join .

2. Спасибо за ваш комментарий, однако я установил рабочие отношения со всеми тремя классами, поэтому я не включил код для остальных. Я следил за документами для ORM, и это сработало прекрасно. Причина, по которой я использовал класс, а не таблицу для объединения, заключается в том, что у меня есть дополнительные поля помимо первичного ключа и внешних ключей. Вместо этого они предлагают вам использовать класс. На данный момент я пытаюсь найти способ получить user_id и country_id, а не идентификатор, и обновить их новой информацией.

Ответ №1:

Вы можете использовать метод filter_by() для фильтрации строк. Например, если вы хотите получить первый user_country, используя user_id и country_id, вы можете использовать следующий запрос:

 user_country = users_countries_join.query.filter_by(user_id=user_id, country_id=country_id).first()
  

Если у вас более одной строки базы данных с одинаковым идентификатором пользователя или идентификатором страны:

 user_country = users_countries_join.query.filter_by(user_id=user_id, country_id=country_id).all()
  

В вашем примере я предполагаю, что вы хотите получить только одну уникальную строку, чтобы вы могли использовать первый запрос.
Кроме того, после изменения значений свойств модели вы должны добавить это изменение в db.session:

 db.session.add(user_country)
  

и фиксирует изменения в базе данных:

 db.session.commit()
  

Я также хочу отметить, что вы должны использовать camel case при объявлении имени класса python, например UserCountry или только Cuntry, и для объединения двух моделей (таблиц) вы не должны определять те же атрибуты, которые у вас есть в классе User или классе Country. На мой взгляд, такой способ объединения двух таблиц является избыточным.