Дринбибиска

Пользователь

Регистрация: 28.05.2013

Сообщения: 4154

Рейтинг: 1840

Дринбибиска

Регистрация: 28.05.2013

Сообщения: 4154

Рейтинг: 1840

img

Добрый вечер PepeSpasibo.gif?1592102734

Надоело плодить темы с разными вопросам, решил для себя создать 1 темку, которую буду апать BrainCosmic.png

____________________________________________________________________________________________

 

Не знаю, как решить вот эту фигню

Спойлер:

У меня получается очень много SQL запросов (чем больше категорий я добавляю -> тем больше запросов получаю) monkaW.png?1592047323

Как правильно написать запрос, чтобы БД отдавал кверисет с моим условием? KEKWait.png?1598747056

Вот модели

Спойлер: "News"
Спойлер: "Category"

saw_tooth

Пользователь

Регистрация: 20.08.2013

Сообщения: 5550

Рейтинг: 3286

saw_tooth

Регистрация: 20.08.2013

Сообщения: 5550

Рейтинг: 3286

Дринбибиска сказал(а):

получается очень много SQL запросов

Нажмите, чтобы раскрыть...

https://stackoverflow.com/questions/97197/what-is-the-n1-selects-problem-in-orm-object-relational-mapping

Дринбибиска

Пользователь

Регистрация: 28.05.2013

Сообщения: 4154

Рейтинг: 1840

Дринбибиска

Регистрация: 28.05.2013

Сообщения: 4154

Рейтинг: 1840

img
saw_tooth сказал(а):
Нажмите, чтобы раскрыть...

Да на самом SQL может я и сам смогу написать(не с 1 раза, но уверен что напишу)

Мне не понятно как это сделать с помощью ORM джанги PeepoWut.png?1576808589

saw_tooth

Пользователь

Регистрация: 20.08.2013

Сообщения: 5550

Рейтинг: 3286

saw_tooth

Регистрация: 20.08.2013

Сообщения: 5550

Рейтинг: 3286

Дринбибиска сказал(а):

Мне не понятно как это сделать с помощью ORM джанги PeepoWut.png?1576808589

Нажмите, чтобы раскрыть...

https://scoutapm.com/blog/django-and-the-n1-queries-problem

Stupid_Squirel

Пользователь

Регистрация: 11.03.2013

Сообщения: 5145

Рейтинг: 5399

Stupid_Squirel

Регистрация: 11.03.2013

Сообщения: 5145

Рейтинг: 5399

моё сообщение на премодерацию ушло...

крч category.news_set.filter(is_published=True). Если я правильно понял, что тебе нужно. А вообще ссылки тебе уже кинули там всё есть

Дринбибиска

Пользователь

Регистрация: 28.05.2013

Сообщения: 4154

Рейтинг: 1840

Дринбибиска

Регистрация: 28.05.2013

Сообщения: 4154

Рейтинг: 1840

img
Stupid_Squirel сказал(а):

моё сообщение на премодерацию ушло...

крч category.news_set.filter(is_published=True). Если я правильно понял, что тебе нужно. А вообще ссылки тебе уже кинули там всё есть

Нажмите, чтобы раскрыть...

Ну я так и написал в цикле  -> стали появляться запросы каждую итерацию

Они хоть и маленькие (~0.06 ms) , но их кол-во зависит от кол-ва категорий

Stupid_Squirel

Пользователь

Регистрация: 11.03.2013

Сообщения: 5145

Рейтинг: 5399

Stupid_Squirel

Регистрация: 11.03.2013

Сообщения: 5145

Рейтинг: 5399

Дринбибиска сказал(а):

Ну я так и написал в цикле  -> стали появляться запросы каждую итерацию

Они хоть и маленькие (~0.06 ms) , но их кол-во зависит от кол-ва категорий

Нажмите, чтобы раскрыть...

тебе не нужен цикл для этого. Фильтр вернет тебе queryset в котором будут категории по твоему условию. Выведи на экран/почитай про filter

Дринбибиска

Пользователь

Регистрация: 28.05.2013

Сообщения: 4154

Рейтинг: 1840

Дринбибиска

Регистрация: 28.05.2013

Сообщения: 4154

Рейтинг: 1840

img
Stupid_Squirel сказал(а):

тебе не нужен цикл для этого. Фильтр вернет тебе queryset в котором будут категории по твоему условию. Выведи на экран/почитай про filter

Нажмите, чтобы раскрыть...

Но я ведь могу фильтровать категорию только по ее полям KEKWait.png?1598747056

Category.objects.filter(title__cointains='test')  и получу все категории у которых есть в названии строка test

 

Могу вот так обратиться  Category.objects.get(pk=4).news_set.filter(is_published=True)

Но мне нужно использовать .all() , а после all я фильтровать не могу, как написал выше

Возможно annotate или prefetch_related  или еще что-то , я еще не разобрался ehh.png?1592046966

Stupid_Squirel

Пользователь

Регистрация: 11.03.2013

Сообщения: 5145

Рейтинг: 5399

Stupid_Squirel

Регистрация: 11.03.2013

Сообщения: 5145

Рейтинг: 5399

Дринбибиска сказал(а):

Но я ведь могу фильтровать категорию только по ее полям KEKWait.png?1598747056

Category.objects.filter(title__cointains='test')  и получу все категории у которых есть в названии строка test

 

Могу вот так обратиться  Category.objects.get(pk=4).news_set.filter(is_published=True)

Но мне нужно использовать .all() , а после all я фильтровать не могу, как написал выше

Возможно annotate или prefetch_related  или еще что-то , я еще не разобрался ehh.png?1592046966

Нажмите, чтобы раскрыть...

открой документацию и посмотри сам, ты по-моему не особо вообще понимаешь, что делаешь... Учитывая что тут уже есть 2 ответа

Дринбибиска сказал(а):

Но я ведь могу фильтровать категорию только по ее полям KEKWait.png?1598747056

Category.objects.filter(title__cointains='test')  и получу все категории у которых есть в названии строка test

 

Могу вот так обратиться  Category.objects.get(pk=4).news_set.filter(is_published=True)

Но мне нужно использовать .all() , а после all я фильтровать не могу, как написал выше

Возможно annotate или prefetch_related  или еще что-то , я еще не разобрался ehh.png?1592046966

Нажмите, чтобы раскрыть...

а, походу наконец дошло что ты сделать хочешь

Дринбибиска

Пользователь

Регистрация: 28.05.2013

Сообщения: 4154

Рейтинг: 1840

Дринбибиска

Регистрация: 28.05.2013

Сообщения: 4154

Рейтинг: 1840

img
Stupid_Squirel сказал(а):

открой документацию и посмотри сам, ты по-моему не особо вообще понимаешь, что делаешь... Учитывая что тут уже есть 2 ответа

Нажмите, чтобы раскрыть...

Я реально не понимаю, что-то или это троллинг? KEKWait.png?1598747056

Или ты не понял что я хочу сделать? KEKWait.png?1598747056

Я просто уже кучу вариантов перепробовал в шеле -> либо ошибки, либо не тот результат KEKWait.png?1598747056

Stupid_Squirel

Пользователь

Регистрация: 11.03.2013

Сообщения: 5145

Рейтинг: 5399

Stupid_Squirel

Регистрация: 11.03.2013

Сообщения: 5145

Рейтинг: 5399

Дринбибиска сказал(а):

Я реально не понимаю, что-то или это троллинг? KEKWait.png?1598747056

Или ты не понял что я хочу сделать? KEKWait.png?1598747056

Я просто уже кучу вариантов перепробовал в шеле -> либо ошибки, либо не тот результат KEKWait.png?1598747056

Нажмите, чтобы раскрыть...

Category.objects.filter(news__is_published=True) попробуй так

Дринбибиска

Пользователь

Регистрация: 28.05.2013

Сообщения: 4154

Рейтинг: 1840

Дринбибиска

Регистрация: 28.05.2013

Сообщения: 4154

Рейтинг: 1840

img

Я хочу что то типо такого (возможно тут будут ошибки  и запрос будет не верный)

SELECT title FROM Category cat

JOIN News ON news.category=cat.id WHERE news.is_published=True

 

Stupid_Squirel сказал(а):

Category.objects.filter(news_set__is_published=True) попробуй так

Нажмите, чтобы раскрыть...

 Cannot resolve keyword 'news_set' into field. Choices are: id, news, title

 

 

upd.

categories = Category.objects.filter(news__is_published=True).distinct()

вот так получил нужный результат Pepego.gif?1593506872Pepego.gif?1593506872Pepego.gif?1593506872Pepego.gif?1593506872

 

А почему в данном случае news , а не news_set KEKWait.png?1598747056 PS: я такой запрос сам уже писал, только ошибку прочитал только что Pepega.png?1599561436

Stupid_Squirel

Пользователь

Регистрация: 11.03.2013

Сообщения: 5145

Рейтинг: 5399

Stupid_Squirel

Регистрация: 11.03.2013

Сообщения: 5145

Рейтинг: 5399

Дринбибиска сказал(а):

Я хочу что то типо такого (возможно тут будут ошибки  и запрос будет не верный)

SELECT title FROM Category cat

JOIN News ON news.category=cat.id WHERE news.is_published=True

 

 Cannot resolve keyword 'news_set' into field. Choices are: id, news, title

 

 

upd.

categories = Category.objects.filter(news__is_published=True).distinct()

вот так получил нужный результат Pepego.gif?1593506872Pepego.gif?1593506872Pepego.gif?1593506872Pepego.gif?1593506872

Нажмите, чтобы раскрыть...

да я случайно `_set` приписал, отредачил уже

Дринбибиска

Пользователь

Регистрация: 28.05.2013

Сообщения: 4154

Рейтинг: 1840

Дринбибиска

Регистрация: 28.05.2013

Сообщения: 4154

Рейтинг: 1840

img
Спойлер: "как было"
Спойлер: "как стало"

Там еще кучу чего нужно исправить, но я думаю сам справлюсь, там полегче PepeCringe.png?1598477741

Дринбибиска

Пользователь

Регистрация: 28.05.2013

Сообщения: 4154

Рейтинг: 1840

Дринбибиска

Регистрация: 28.05.2013

Сообщения: 4154

Рейтинг: 1840

img

Покопался в документации джанго, можно писать SQL запросы вручную PogChamp.png?1548076456

Спойлер:

Правда DISTINCT почему то не отработал (попозже разберусь)

Вот это имеют ввиду работодатели, когда пишут в вакансиях "SQL в обход ORM" ? pepethink.png?1592046698

Дринбибиска

Пользователь

Регистрация: 28.05.2013

Сообщения: 4154

Рейтинг: 1840

Дринбибиска

Регистрация: 28.05.2013

Сообщения: 4154

Рейтинг: 1840

img

F5 RoflanTsar.png?1579941445

 

Доброй ночи  2xрамисты

 

Насколько правильно я реализовал аутентификацию по логину либо емейлу?

https://github.com/BeginnerA234/Django-Custom-User

 

UPD: Плохое решение от меня не учитывать регистр при просмотре логина т.к в бд можно сохранить User и uSer -> при проверке вылетает ошибка

oct2048

Пользователь

Регистрация: 05.09.2017

Сообщения: 199

Рейтинг: 113

oct2048

Регистрация: 05.09.2017

Сообщения: 199

Рейтинг: 113

Дринбибиска сказал(а):

Насколько правильно я реализовал аутентификацию по логину либо емейлу?

Нажмите, чтобы раскрыть...

Ты её вообще не реализовал.

Бэкенд аутентификации должен содержать два метода: authenticate() и get_user(). У тебя есть кривой authenticate() и отсутствует get_user().

Комментарий к классу EmailAndLoginAuthBackend совершенно не соответствует сути, я бы за подобное выпорол джуна.

Дринбибиска

Пользователь

Регистрация: 28.05.2013

Сообщения: 4154

Рейтинг: 1840

Дринбибиска

Регистрация: 28.05.2013

Сообщения: 4154

Рейтинг: 1840

img
oct2048 сказал(а):

Ты её вообще не реализовал.

Бэкенд аутентификации должен содержать два метода: authenticate() и get_user(). У тебя есть кривой authenticate() и отсутствует get_user().

Комментарий к классу EmailAndLoginAuthBackend совершенно не соответствует сути, я бы за подобное выпорол джуна.

Нажмите, чтобы раскрыть...

Окей, возможно я не правильно выразился KEKWait.png?1598747056

Изменил правило аутентификации Pepega.png?1599561436

Метод get_user наследуется ведь KEKWait.png?1598747056

И в чем кривость authenticate? Что исправить ?PepeWh.gif?1610052035

Комментарий считаю верным. Почему он не правильный? 

Меня на локалке пускает в админку и по емейлу и по логину. Прочих юзеров не пускает

Dante_^

Пользователь

Регистрация: 22.10.2012

Сообщения: 1472

Рейтинг: 533

Dante_^

Регистрация: 22.10.2012

Сообщения: 1472

Рейтинг: 533

oct2048 сказал(а):

Ты её вообще не реализовал.

Бэкенд аутентификации должен содержать два метода: authenticate() и get_user(). У тебя есть кривой authenticate() и отсутствует get_user().

Комментарий к классу EmailAndLoginAuthBackend совершенно не соответствует сути, я бы за подобное выпорол джуна.

Нажмите, чтобы раскрыть...

козел а нужно попробовать нормально объяснить

oct2048

Пользователь

Регистрация: 05.09.2017

Сообщения: 199

Рейтинг: 113

oct2048

Регистрация: 05.09.2017

Сообщения: 199

Рейтинг: 113

Дринбибиска сказал(а):

Метод get_user наследуется ведь

Нажмите, чтобы раскрыть...

Все верно, не обратил внимание, что ты наследуешься от ModelBackend, я бы сделал обычный object.

Дринбибиска сказал(а):

И в чем кривость authenticate? Что исправить ?

Нажмите, чтобы раскрыть...

У тебя три ветки логики:

1. Пользователь найден, пароль верен -> return user

 по этой ветке вопросов нет

2. Пользователь найден, пароль не верен -> обработчика нет

 как минимум тут надо делать return None

3. Пользователь не найден -> делаешь не пойми что

 как минимум нужен return None или return user, если ты хотел его создать.

 

Попробуй такой вариант:

#settings.py

AUTHENTICATION_BACKENDS = <

    'django.contrib.auth.backends.ModelBackend',

    'account.authentication.EmailAuthBackend',

]

 

 

#auth.py

class EmailAuthBackend(object):

    """

    Выполняет аутентификацию пользователя по e-mail.

    """

    def authenticate(self, request, username=None, password=None):

        try:

            user = User.objects.get(email=username)

            if user.check_password(password):

                return user

            return None

        except User.DoesNotExist:

            return None

 

        def get_user(self, user_id):

            try:

                return User.objects.get(pk=user_id)

            except User.DoesNotExist:

                return None

 

Дринбибиска сказал(а):

Комментарий считаю верным. Почему он не правильный?

Нажмите, чтобы раскрыть...

Ответь себе на  вопросы:

1. Для кого пишут описание классов?

2. Для чего пишут?

3. Соответствует ли написанное тобой описание первым двум вопросам?

 

Больше читай чужой код, желательно профессиональный и обращай внимание на то, как там оформляют код.

Еще тебе на подумать.

В стандартной модели User, поле email не уникально, т.е. может быть несколько юзеров с одинаковыми емейлами. Более того, могут быть юзеры у которых в username написан емейл.

Исходя из этого 

    user = CustomUser.objects.get(Q(username=username) | Q(email=username))

не стабильно. Нужен обработчик исключения MultipleObjectsReturned

Дринбибиска

Пользователь

Регистрация: 28.05.2013

Сообщения: 4154

Рейтинг: 1840

Дринбибиска

Регистрация: 28.05.2013

Сообщения: 4154

Рейтинг: 1840

img
oct2048 сказал(а):

Все верно, не обратил внимание, что ты наследуешься от ModelBackend, я бы сделал обычный object.

У тебя три ветки логики:

1. Пользователь найден, пароль верен -> return user

 по этой ветке вопросов нет

2. Пользователь найден, пароль не верен -> обработчика нет

 как минимум тут надо делать return None

3. Пользователь не найден -> делаешь не пойми что

 как минимум нужен return None или return user, если ты хотел его создать.

 

Попробуй такой вариант:

#settings.py

AUTHENTICATION_BACKENDS = <

    'django.contrib.auth.backends.ModelBackend',

    'account.authentication.EmailAuthBackend',

]

 

#auth.py

class EmailAuthBackend(object):

    """

    Выполняет аутентификацию пользователя по e-mail.

    """

    def authenticate(self, request, username=None, password=None):

        try:

            user = User.objects.get(email=username)

            if user.check_password(password):

                return user

            return None

        except User.DoesNotExist:

            return None

 

        def get_user(self, user_id):

            try:

                return User.objects.get(pk=user_id)

            except User.DoesNotExist:

                return None

 

Ответь себе на  вопросы:

1. Для кого пишут описание классов?

2. Для чего пишут?

3. Соответствует ли написанное тобой описание первым двум вопросам?

 

Больше читай чужой код, желательно профессиональный и обращай внимание на то, как там оформляют код.

 

Еще тебе на подумать.

В стандартной модели User, поле email не уникально, т.е. может быть несколько юзеров с одинаковыми емейлами. Более того, могут быть юзеры у которых в username написан емейл.

Исходя из этого 

    user = CustomUser.objects.get(Q(username=username) | Q(email=username))

не стабильно. Нужен обработчик исключения MultipleObjectsReturned

Нажмите, чтобы раскрыть...

Спасибо за развернутый ответ PeepoHappy.png?1596274122

Завтра буду все пробоватьPepego.gif?1593506872

Комментарии ещё учусь писатьPepeWh.gif?1610052035

А поводу email я его сделал в модели уникальным  PeepoHappy.png?1596274122

P.s: только эта уникальность будет скорее всего криво работать т.к уникальным считается любое изменение регистра, а не сам адресс.

Нужно email в нижнем регистре записывать

 

 

oct2048

Пользователь

Регистрация: 05.09.2017

Сообщения: 199

Рейтинг: 113

oct2048

Регистрация: 05.09.2017

Сообщения: 199

Рейтинг: 113

Дринбибиска сказал(а):

А поводу email я его сделал в модели уникальным

Нажмите, чтобы раскрыть...

Этого не достаточно. То что ты описал у себя в модели, приведет к созданию констреинта в базе данных, но то как будет обрабатываться этот констреинт зависит от конкретного экземпляра СУБД (там есть опция регистрозависимости).  Нужно чекать этот момент.

Дринбибиска сказал(а):

эта уникальность будет скорее всего криво работать т.к уникальным считается любое изменение регистра

Нажмите, чтобы раскрыть...

Это зависит от опции СУБД.

Дринбибиска сказал(а):

Нужно email в нижнем регистре записывать

Нажмите, чтобы раскрыть...

Да, но тут тоже не всё однозначно. Если есть варианты редактирования записи в БД не из твоего приложения (например админ может править таблицы напрямую через инструменты СУБД), то нужно приводить в нижний регистр на стороне СУБД, например делать  калькулейтед поле или триггер.