Pull to refresh

Comments 17

«followed = db.relationship('User', secondary = followers, primaryjoin = (followers.c.follower_id == id), secondaryjoin = (followers.c.followed_id == id), backref = db.backref('followers', lazy = 'dynamic'), lazy = 'dynamic')
Post.query.join(followers, (followers.c.followed_id == Post.user_id)).filter(followers.c.follower_id == self.id).order_by(Post.timestamp.desc())»

Ммм как же я люблю ORM…

SELECT *
FROM posts
WHERE author IN
(SELECT followed FROM followers WHERE follower=?)
ORDER BY timestamp
Спасибо за Ваш перевод. Хотел бы отметить, что было бы лучше (нагляднее), если б те манипуляции с объединением данных (join) из таблиц Вы сделали в виде картинок или взяли из первоисточника.
Замечание справедливое. Самому не нравилось. Торопился.
Поправьте пожалуйста ссылку на следующую статью — «следующая >>>» сейчас она указывает на эту статью.
Поправил проверил теперь все правильно. Спасибо за внимательное прочтение!

Привет!


Что-то не пойму, как это работает:


if user == current_user:

Эти объекты разные, если смотреть функцией id(), получается сравнение идет по атрибутам класса. Где это реализовано, в каком классе?

Всё. Нашел случайно )) Реализовано в миксин-классе UserMixin:


class UserMixin(object):
    ...
    def __eq__(self, other):
        ...
    ...

Может кто подскажет, как в Python увидеть, в каком родительском классе реализуется конкретный метод? Не просто класс который реализует метод, так как метод теоретически может реализовываться в каждом из них, а тот, который действует на конечный результат?


Например, в этом примере ясно, что переопределяется в UserMixin, а если бы метод _eq_ реализовывался где нибудь в недрах API flask-sqlalchimy или в самой sqlalchimy, как это найти, есть ли какие инструменты?

TYPE.__MRO__

Содержит кортеж с родительскими типами, выстроенными в порядке разрешения методов.
Свойство доступно только для чтения.

Порядок разрешения методов (Method Resolution Order — MRO), рассчитанный при помощи алгоритма C3 представляет собой линеаризацию (построение линейного вида) иерархии классов. Алгоритм позволяет разрешить возможные конфликтные ситуации при множественном наследовании (конфликт методов, проблема ромба).

Два (из трех — C3) основных правила линеаризации:
1. дети идут раньше родителей;
2. родители идут в порядке перечисления.
    list.__mro__  # (list, object)

    class A(object): pass

    class B(A): pass

    class C(A): pass

    class BC(B, C): pass

    BC.__mro__  
    # (__main__.BC, __main__.B, __main__.C, __main__.A, object)


дальше иди по классам справа налево и ищи в них метод который тебя интересует. Последний найденный и будет использоваться твоим экземпляром.

И еще такой вопрос, а как получается, что таблица (или переменная) followers объявленная вне класса, над классом User доступна из объекта класса?


Пример:


файл /app/models.py:


...

followers = db.Table('followers',
    db.Column('follower_id', db.Integer, db.ForeignKey('user.id')),
    db.Column('followed_id', db.Integer, db.ForeignKey('user.id'))
)

class User(UserMixin, db.Model):

    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), index=True, unique=True)
    email = db.Column(db.String(120), index=True, unique=True)
    password_hash = db.Column(db.String(128))
...

Затем это как-то доступно в шаблоне — user.followers.count():


...
<p>
    {{ user.followers.count() }} followers, {{ user.followed.count() }} following.
</p>
...

и при этом не понятно, как работает count() в конструкции user.followers.count(), если вне класса обявлена только таблица и её колонки? Что-то вообще всё не явно.

Таблица followers — это таблица ассоциаций отношений или таблицей относительных связей. Внешние ключи ( foreign keys ) в этой таблице указывают на записи в пользовательской таблице, поскольку они связывают пользователей с пользователями. Мы к самой таблице обращаемся через внешние ключи. В шаблоны объект user передается в вьюшке (routes.py)

К этой статье указаны одни из следующих тегов: flowers, flowed
Это шутка такая, намеренно сделано? Или это опечатка и вместо последователей внесены цветочки и течь? ))

localhost:5000/follow/Susan
Модифицирующие операции GET-запросами делать не стоит.

Какой ужас этот ORM.

Вместо простого запроса "SELECT COUNT(*) FROM folowers WHERE folower_id=? AND folowed_id=? LIMIT 1;" такой трэш и угар. Судя по всему в предложенной версии зачем-то сначала составляется список всех подписанных пользователей, и потом по нему прогоняется отдельный запрос для нужного юзера.

Да и в поиске постов можно было прекрасно обойтись без union. Сдаётся мне, что с таким конструированием запросов не только падает наглядность, но и растёт время их выполнения.

....Хороший ORM – отсутствующий ORM.... :) Это не моё. Это здесь https://habr.com/ru/post/458286/

И ещё:...Как правило, «низкоуровневый» API базы данных прост, удобен, полон и консистентен....

Так что, есть и такие точки зрения. Всё зависит от привычек и "нравится/не нравится".

В комментариях статьи, на которую я привёл ссылку, есть доводы в защиту ORM. Там много интересного. А здесь просто перевод главы из публикации Мигеля Гринберга.

Sign up to leave a comment.

Articles