Отношения один-к-одному в Flask-SQLAlchemy работают только в одном направлении - PullRequest
0 голосов
/ 23 января 2019

У меня есть две модели в приложении колбы, они формируют отношение один-к-одному, где модель «Персонал» может быть связана с одним «Пользователем».Может быть «Персонал» без того, чтобы они были «Пользователем», но не «Пользователь», не будучи «Персоналом».

К сожалению, я падаю на первое препятствие.Я пытаюсь объединить модели в HTML-таблицу, созданную на основе Jinja2.Предполагается, что в таблице перечислены все «сотрудники» и определено, являются ли они «пользователями».Если они «Пользователь», то он должен определить, активны они или нет.

Вот мои модели в их нынешнем виде:

class Staff(db.Model):
    __tablename__ = 'staff'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80), nullable=False)
    job_title = db.Column(db.String(255), nullable=True)
    is_user = db.Column(db.Boolean, nullable=False, default=False)
    user = db.relationship('User', 
        backref=db.backref('staff', lazy=True))

    def __repr__(self):
        return f'Staff Member: {self.id}, {self.name}, {self.job_title}'


class User(db.Model, UserMixin):
    __tablename__ = 'user'
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(120), unique=True, nullable=False)
    image_file = db.Column(db.String(20), nullable=False, 
        default='default.jpg')
    password = db.Column(db.String(255), nullable=False)
    active = db.Column(db.Boolean, nullable=False, default=False)

    staff_id = db.Column(db.Integer, db.ForeignKey('staff.id'), 
       nullable=False)

    def __repr__(self):
        return f'User({self.name}, {self.email}, {self.image_file})'

А здесьэто пример отношений в Jinja2.Этот сегмент кода работает, как и ожидалось:

{% for user in users %}
<tr>
    <td>{{ user.staff.name }}</td>
    <td>{{ user.staff.job_title }}</td>
    <td>{{ user.email }}</td>
    {% if user.active == True %}
    <td>Yes</td>
    {% else %}
    <td>No</td>
    {% endif %}
{% endfor %}

Этот код, однако, где я пытаюсь получить информацию о пользователе, в то время как циклически просматривая весь «Персонал», не работает наall:

{% for staff in all_staff %}
    <tr>
        <td>{{ staff.name }}</td>
        <td>{{ staff.job_title }}</td>
    {% if staff.is_user == True %}
        {% if staff.user.active == True %}
        <td class="text-success">Yes (Active)</td>
        {% elif staff.user.active == False %}
        <td class="text-warning">Yes (Inactive)</td>
        {% endif %}
    {% elif staff.is_user == False %}
        <td class="text-danger">No</td>
    {% endif %}
{% endfor %}

Хотя связь работает одним способом, она не работает во втором примере таблицы;он вообще не возвращает HTML-код, если только staff.is_user == False не верен.

Я пытался создать новый db.relationship в классе 'User'.Я также попробовал db.relationhip в обоих классах одновременно.Я также пробовал использовать операторы Jinja2 if в одной строке:

{% if staff.is_user == True and staff.user.active == True %}

Однако ни один из них не работает, и где я ожидаю, что будет возвращен правильный htmlосновываясь на результатах операторов if, я не получаю никаких результатов при обращении к таблице «Users» через таблицу «Staff».

Я уверен, что упускаю что-то простое, но яне могу понять.

Кто-нибудь может увидеть, где я иду не так?

1 Ответ

0 голосов
/ 28 января 2019

Получается, что ответ скрывался в разделе «Отношения« один на май »» в Flask-SQLAlchemy docs . Чтобы ссылаться на отношение «один к одному», необходимо установить uselist=False в отношении. Точно так же, как это звучит, он загружает соединение как скаляр, а не список.

Я также допустил ошибку, когда брал некоторую информацию из основных документов SQLAlchemy и неправильно загружал обратную ссылку в отношениях. В Flask-SQLAlchemy его просто нужно объявить как строку. В этом случае backref='staff'.

Этот код работает точно так же, как и ожидалось:

class Staff(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80), unique=True, nullable=False)
    job_title = db.Column(db.String(80))
    is_user = db.Column(db.Boolean, default=False)
    user = db.relationship('User', backref='staff', lazy=True, uselist=False)

    def __repr__(self):
        return f'Staff Member: {self.id}, {self.name}, {self.job_title}'


class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(120), unique=True, nullable=False)
    active = db.Column(db.Boolean, nullable=False, default=False)
    staff_id = db.Column(db.Integer, db.ForeignKey('staff.id'), nullable=False)

    def __repr__(self):
        return f'User Account: {self.id}, {self.email}'
...