#python #sqlite #flask #sqlalchemy
Вопрос:
Я создаю приложение для планирования событий с помощью Flask и пытаюсь написать функцию, которая возвращает все события, видимые текущему пользователю. К ним относятся:
- Собственные события пользователя
- Все публичные мероприятия
- Друзья-только события, принадлежащие друзьям пользователя
- События только по приглашению, на которые пользователь был приглашен/получил приглашение
Вот соответствующие модели и таблицы:
friendship = db.Table('friendships', db.Model.metadata,
db.Column('a_id', db.Integer, db.ForeignKey('users.id'), primary_key=True),
db.Column('b_id', db.Integer, db.ForeignKey('users.id'), primary_key=True)
)
class User(db.Model, UserMixin):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
events = db.relationship('Event', backref='author', lazy='dynamic')
friends = db.relationship('User',
secondary=friendship,
primaryjoin=id==friendship.c.a_id,
secondaryjoin=id==friendship.c.b_id,
lazy='dynamic')
# Filter in case event privacy has been updated
def associated_events(self, user=None):
return self.invited_events
.union(self.going_events)
.union(self.not_going_events)
.filter(~Event.privacy == 1)
# going and not_going are virtually identical
invited = db.Table('invited_users_table', db.Model.metadata,
db.Column('event_id', db.Integer, db.ForeignKey('events.id'), primary_key=True),
db.Column('user_id', db.Integer, db.ForeignKey('users.id'), primary_key=True)
)
class Event(db.Model):
__tablename__ = 'events'
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
# 1 - private, 2 - invite only, 3 - friends only, 4 - public
privacy = db.Column(db.Integer, default=1)
# going_users and not_going_users are virtually identical
invited_users = db.relationship('User',
secondary=invited,
backref=db.backref('invited_events', lazy='dynamic'),
lazy='dynamic')
Я написал функцию, которая работает, но она очень медленная и, по общему признанию, взломана с помощью нескольких часов проб и ошибок:
def visible_events():
# Public events
result = Event.query.filter(Event.privacy == 4)
if current_user.is_authenticated:
result = result.union_all(
# Own events
current_user.events,
# Invited/RSVP'd events
current_user.associated_events(),
# Friends' events
Event.query.filter(Event.privacy == 3)
.join(User, Event.author)
.join(friendship, friendship.c.a_id == User.id)
.filter(friendship.c.b_id == current_user.id)
)
return result
Есть ли лучший способ подойти к этой функции или, возможно, к базовым классам и таблицам? Спасибо!
Комментарии:
1. Именно по этой причине я просто пишу запросы в своем коде и вызываю sql, а также обхожу ORM все вместе.
2. @eatmeimadanish, я вижу. На самом деле я никогда не писал SQL, и до этого проекта я вообще никогда не работал с базой данных. Извините, но у вас есть какие-нибудь предложения по написанию такого сложного запроса?