#15. Классы представлений: ListView, DetailView, CreateView | Django уроки
ฝัง
- เผยแพร่เมื่อ 28 ต.ค. 2024
- Практический курс по Django: stepik.org/a/1...
Django урок 15. Что такое классы представлений (Class-Based Views - CBV), как создаются и подключаются к маршрутам (метод as_view()). Атрибуты: model, template_name, context_object_name, extra_context, allow_empty. Методы: get_context_data(), get_queryset(). Атрибуты класса DetailView: slug_url_kwarg, pk_url_kwarg. Атрибут класса CreateView: form_class и success_url. Функция reverse_lazy() и ее отличие от reverse().
Телеграм-канал: t.me/django_se...
Инфо-сайт: proproprogs.ru...
lesson-15-coolsite.zip: github.com/sel...
Список базовых классов: djbook.ru/rel1...
Русскоязычная документация по Django 3: djbook.ru/rel3.0/
Официальный сайт по Django: www.djangoproj...
Картинки всё горячее с каждым уроком. Смотрю дальше)
Пытаюсь предугадать ваши действия, пишу код сам и проверяю по вам. Когда получается, радости полные штаны)
Насколько грамотная речь! И материал, и подача. Мне все очень понравилось
Урок просто блестящий. В одном уроке я столько своих вопросов закрыл, что нет слов. Удачи автору!
На много упрощает код. Благодарю за видеоматериал!
Спасибо, Сергей! Сегодня займусь Вашим курсом по ООП. Все отлично.
я думала мы вместо allow_empty = False будем ручками прописывать условие и рейзить Http404, а оказывается и для этого свой аттрибут есть)) мне прям даже как то неудобно, что джанго за нас все делает 😀
Сергей, вы прекрасный учитель. К сожалению, столкнулся с проблемой, что теперь хочу учить материал исключительно по вашим урокам. :) Мне кажется, что ученикам было бы очень интересно учить вместе с вами git или хотя-бы gitlab. Вы лучший. Спасибо большое за ваши труды.
Супер! Спасибо! Это очень существенная особенность Django!
Спасибо огромное!! Так рассказывать это дар! Спасибо!
Спасибо очень доступно, то что нравится на вашем канале!
Большое спасибо! По документации не очень понятно, как оно всё работает, теперь документацию можно смотреть более осознанно
Спасибо Вам за урок! Очень интересная тема! Теперь главное правильно выбирать класс родитель) Круто!
Я посмотрел только 6 минуту, но уже понял что ты топовый програмист, подписка и лайк, удачи в продвижении
Спасибо Вам за такую полезную информацию, Вы спасли мой проект))
оооо... супер👍 в основном ради class based views смотрел этот курс
Как всегда, видеоурок на высоте!
Чувствую, что к 26 уроку фотографии уже нужно будет цензурить😄
А ты думал для чего там галочка не публичные)
Спасибо, Сергей, за твои уроки!
На этом примере понял, как удобно использовать Templatetags. Так как я ранее менюшку сайта вынес в отдельный тег, то сейчас не нужно постоянно ее прописывать
Автор - ты лучший!
Учитель от Бога
Из этого занятия стало понятно, что автор не выполнил домашнее задание по отображению главного меню через включенный тег))
Мой маленкий совет для всех сделать кнопу "админ" в меню, чтобы в процессе содания сайта быстро переходить на страницу администратора!) просто настроить для нее url и написать функцию с содержимым "pass"
а потом менять фронтенд, когда будешь её удалять
разве написать admin в адресе долго ?
спасибо за такие замечательные уроки. Смотрю этот курс и параллельно документацию на русском языке, очень удобный комплект для обучения получается) потом уже если углубляться, не так страшно будет)
Thank you, sir!
Решил вернуться к этой теме, на своём проекте реализовать DetailView. Долго мучался с FieldError. Оказалось дело в том, что у меня в модели по-другому поле со слагом называется. Итого решение - надо переопределить параметр slug_field - присвоить ему название слага в моей модели
Привет! Все супер, но у меня вопрос: на 24й минуте строка 88 context['title'] = context['post'] по моему она сработала только потому, что у класса был определен метод __str__, не будет ли более правильно написать context['title'] = context['post'].title? Какое Ваше мнение?
Да, совершенно верно! Вы первый, кто это отметил! Наверное, лучше все-таки явно указывать title, чтобы избежать возможных ошибок, здесь я с Вами полностью согласен.
@@selfedu_rus Думаю если ещё можно, то стоит отметить это в описании видоса
Приветствую! Отличное уточнение, только не tYtle, а title. Исправьте, пожалуйста, чтобы кто-то не повторил опечатку. Спасибо!
@@dmitryzagorevskiy507 Спасибо, попоавил.
Красиво, спасибо огромное
Спасибо!
Надеюсь, у вас появятся видео по переводу сайта на другие языки
??? в настрой поставить другой язык и все вроде
@@vladkrolik2700 нууу почти...=)
@@stevejops007 Фамилия как у меня )
Не совсем понятен механизм сохранения формы и добавление поста в базу данных. Не могу понять в какой момент, почему и откуда Джанго знает о том, что нужно добавить данные в базу данных в классе AddPage. Был бы благодарен, если бы Вы мне смогли обьяснить!)
нейминг божественный конечно
Здравствуйте. Можете подсказать, в джанго kwargs имеет только параметры маршрута, или еще что-то?
Вот это упростили конструкцию так упростили )))) было 3 строчки кода стало 23 ))))))))
Спасибо
Можно добавить в class show_post функцию
def get_queryset(self):
return Women.objects.filter(is_published=True)
если без нее, то можно открыть не опубликованный пост по слагу
в тестирование переиграл :)
Мне кажется лучше использовать get_object(self):
def get_object(self):
"""Выбор нужной записи из таблицы 'Women'"""
return get_object_or_404(Women, slug=self.kwargs['post_slug'], is_published=True)
Так как я использовал ваш вариант и пытался просто filter() заменить на get() и выдавало ошибку, что оно находит не 1, а сразу 5 записей, что натолкнуло меня на мысль, что нужно туда добавить в условие проверку по slug(но оставить использовать filter()) или найти в документации Django подходящую функцию, для получения одной записи(как я показал в самом начале).
Круто! Отдельное спасибо за фотки барышень)
здравствуйте, извините, при проектирование подобного сайта возник вопрос, а что делать, если, условно, я хочу вывести в блок контента не только статьи, но и сами категории, вот так к примеру, певица: Пугачева, Лолита; актрисы: ходченкова; и возникает ВОПРОС, а как корректно передать класс представления несколько моделей ? Не уверен, что смогу получить ответ, но все же мало ли, заранее спасибо за ответ, многоуважаемый автор!!!
мне кажется в 17:38 для отображения заголовка лучше использовать f строку(context['title'] = f"Category: {context['publications'][0].cat}")
мужык, ты лучший
Единственное, непонятно теперь, может кто объяснит, как класс понимает какой слаг передали
И как он его обрабатывает?
спасибо за видос )
Ох же, сложновато! Буду разбираться, но смогу :)
Сергей, спасибо за уроки! Подскажите, почему класс WomenCategory работает без указания slug_url_kwarg, а ShowPost нет?
ой я уж спустя 2,5 года и не помню что за WomenCategory )) спросите в сообществе телеграм-канала, вам там подскажут.
Спасибо за превосходное объяснение. Это лучшее, что я находил.
Есть вопрос по этим классам. Во все классы мы добавляли динамический контекст. Можно объявить базовый класс с этими методами и далее наследоваться в дальнейшем? Или я забегаю вперед?
да, конечно, весь спектр возможностей ООП здесь можно применять
Спасибо! шаг за шагом появляется ясность. У меня вопрос. Если модель1 имеет форин кей к другой модели2, и мне нужно сделать форму по добавлению записи в модель1. Как мне это сделать? джанго ругается, что поле не ссылается на внешнюю модель2 (мне понятно, что там такой записи нет). Как сделать, чтобы объединить такое добавление? просто сделать модель2.objects.create(поле='значение') и потом form.save()?? или есть проще метод?
Лучше это обсудить в ТГ-канале (ссылка под видео). А в двух словах, Django, скорее ругается, что поле не заполнено (а не то, что оно не связано, связь, как раз в модели указана). Тут возможно параметр default нужно еще прописать, тогда при добавлении новой записи в модель2 пойдет значение по умолчанию, но тогда оно будет дублироваться, а это, скорее всего, недопустимо. В общем, надо подумать, чтобы не было дублирования и значение автоматом прописывалось. Варианты есть.
Здравствуйте. Использую ваш курс как наглядный пример и как посредник между документацией (смотрю как делаете вы - читаю про это в документации, книге или гугле. Так, сухая документация подкрепляется реальной структурой и выстраивается полная картина проекта). Спасибо огромное. Но информации очень много и усвоить без большого количества практики - невозможно. Можете посоветовать хорошее задание? С одной стороны нагугленные по запросу проекты "для джуниор джанго дев" ещё слишком абстрактные и сложные, с другой стороны сделать простые несколько страниц сайта, с несложными моделями и логикой я уже умею. Спрашиваю на случай если у вас есть хорошее отработанное задание, а так, конечно, буду искать сам, благо технология не малоизвестная. В целом просто хотел сказать вам спасибо. Ваш канал - это находка. Обязательно послушаю про генетические алгоритмы и многое другое, после того как смогу начать реальную работу в текущей области)
Спасибо! Заданий так то не делал. Как вариант попробуйте сделать более сложный сайт с набором большого числа изображений (например, формул в тексте). Подумайте как хранить такие страницы на стороне сервера, как загружать. Еще вариант сделать простой форум.
Подскажите пожалуйста, если я еще на прошлом уроке наш список menu "обернул" в inclusion_tag и передал функцию в base.html будет ли это "ошибкой" или недочетом, хотя теперь наше меню у нас есть всегда)
можно, ошибки не будет
@@selfedu_rus благодарю вас!)
Всё прекрасно, но есть вопрос, почему бы WomenCategory не наследовать от WomenHome и просто переопределить нужные методы? Просто ключевое отличие в фильтре.
ИЛИ сделать всё ещё хитрее и определить некий WomenView где мы допустим будем указывать все стандартные методы(допустим настройки header) и от него уже дальше наследоваться.
У меня почему то не отображаются поля в классах CreateView и FormView. Может из-за того что они унаследованы от ModelForm в файле forms.py?
На 7:04 сказано, что можно передавать только неизменяемые данные в extra_context,
но такой код сработал (использую Django 4. Возможно, в третьей версии нельзя было):
class Mixin():
menu = [{'title':'статьи','url':'list'},
{'title':'новая','url':'new'},
{'title':'инфо','url':'about'},
{'title':'тема','url':'theme'},
{'title':'вход','url':'login'}
]
context = {
'menu': menu,
'style': styles[0]
}
class List_page(Mixin, ListView):
'''ОТОБРАЖЕНИЕ СПИСКА СТАТЕЙ'''
model = Page
context_object_name = 'list'
template_name = 'pager/list.html'
extra_context = Mixin.context
Закинул меню таким же списком в словарь context миксина, а потом, наследовав (Mixin, ListView),
передал в extra_context этот список Mixin.menu, и всё заработало в таком простом формате.
p.s. спасибо за уроки, Сергей!
Да, я здесь не совсем верно сказал, в extra_context можно прописывать только те данные, которые известны (существуют) на момент описания класса.
На примере первых двух классов представлений и не скажешь, что есть выигрыш в количестве кода, функции выглядят компактнее.
В реальности кода в функциях представлений гораздо больше, особенно, при работе с формами и здесь классы представлений очень выручают.
Спасибо большое за урок!
У меня возник вопрос: зачем в определении функции
def get_context_data(self, *, object_list=None, **kwargs):
мы передаем "*" и "object_list=None", если оно все равно не используеться?
Мне кажется что оно используется, просто когда его все же нет, мы передаём его как None. Чтобы Джанго не выдавал ошибку
@@stmustbkя его из кода убрал . Ничего вроде не поменялось
@@nevermore222 в старых версиях приходилось его писать
@@stmustbk а ну то есть сейчас достаточно писать self в аргументах и более ничего не указывать и он будет работать? Теперь вроде бы ясно стало спасибо
А что с ссылкой "Список базовых классов" в описании?
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
name = Category.objects.get(slug=self.kwargs['category_slug']).name
context['title'] = f'Категория - {name}'
return context
Так тоже работает вывод названия категории в заголовок
Спасибо за уроки. Возник диссонанс. Почему template_name - index.html, но в urls мы указываем category html.
Сергей, не обязательства ради, а понимания для, не могли бы Вы примерно сориентировать какие у Вас предположительные прогнозы по времени начала и окончания вашего очередного шедеврального курса по Django REST framework? Заранее большое спасибо хотя бы за очень приблизительный прогноз по времени.
думаю, в конце января начнем )
Когда лучше использовать классы представления, а когда функции?
Большое спасибо за супер уроки!
Пожалуйста ответьте на один вопрос: Если в адресном поле пишем адрес тогда всё понятно, вызывается функция path и ищет соответствие адреса к маршруту и если есть соответствие тогда вызывается представление и потом уже шаблон.
А вот когда нажимаем кнопку "читать пост" тогда кто кого вызывает? Откуда начинается цепь вызовов? В этом случае в адресном поле мы же ничего не пишем!
Когда нажимаете на кнопку, то это такой же переход по URL-адресу, который в ней прописан. Если это обычная ссылка, то имеем GET-запрос к серверу, если форма, то может быть и дургой тип запроса.
@@selfedu_rus Понял. Спасибо!
вопрос, почему на каждый шаблон мы передаем menu неужели нельзя сделать в базовом шаблоне и больше к нему не возвращаться?
Спасибо, прекрасный урок. Но возник один вопрос. 24:29 , 51 строка, почему нельзя использовать редирект на ‘home’?
Так можно или нельзя? Самому интересно
Я пересматриваю уроки, спасибо! Хотя уже работаю программистом
Привет! Спасибо за уроки! Один момент я написал extra_context и передал туда меню и у меня все сработало без функции Def get_context_data
Потому что в данном случае у нас меню это статичная переменная, но если она будет меняться динамически, в зависимости от того какая страница у нас представлена то что-то пойдет не так.(допустим меню генерирует отдельная функция по объекту который передается в нее из класса или что-нибудь подобное).
Спасибо за уроки, самые лучшие в TH-cam ! У меня вопрос: Вы показали , как сделать автоматическое заполнение поля slug в меню-админа, а как сделать это через поле формы (где ее добавляет пользователь через CreateView... -.)?
средствами JS, можно самостоятельно написать, можно найти фрагмент на просторах Интернета
Спасибо за урок!
Но почему бы в get_queryset не возвращать вместо "Women.objects.filter(...)" "self.model.objects.filter(...)"?
Упс... я уже сейчас такую тонкость не помню )
Супер!) Дякую:)
Респект!!!
Вы говорите что в словаре extra_context можно передавать только статические данные, это не так. У меня любые данные работают: списки, выборки из моделей, можно хоть форму передать. Меню отлично передается и работает. Я что то упускаю?
кстати, я вот сижу и думаю, а почему у меня меню отображается? Потом вспомнил, что мы делали свой тег для категорий и для меню по желанию. Удобно
Вот я что то не понимаю . А зачем в аргументах get_context_data - '*' и 'object_list=None' ? Я их вроде удалил и ничего не поменялось . Да и нигде не используется оно вроде бы
Объясните пожалуйста, в каких случаях лучше использовать какой класс View
В зависимости от вида выдаваемой информации на странице (список, статья, форма и т.п.).
context["posts"][0].cat работает только в том случае, если есть хотя-бы одна запись, У меня идет еще категория "Другое" без записей, и она так не отображается, падает ошибка
Очень круто и профессионально. Мне очень нравится. Жаль только что сайт закрыт. Не понимаю, так мало времени прошло
При cat тоже работает context['cat_selected'] = context['posts'][0].cat - вместо cat_id - я помню Сергей говорил, что это почти одно и то же - я проверил в shell и там cat возвращает то что мы определили в __str__ в модели, а cat_id - pk (id, fk - кому как угодно) Category - я так понимаю мы ставили там cat_id для шаблона list_categories - но при изменении про которое я написал - всё работает - кто-то может объяснить почему?
Добрый вечер!
Как правильнее то в итоге делать: на функциях или на объектах???
зависит от задачи, как удобнее
хмб.. у меня меню уже в пользтегах, вот если оно так, то могу же я просто выдернуть словари из тегов?? только не получается чего-то
Спасибо!
Годнота-то какая))
Лепота)
Спасибо, суть понятна! Но кажется, что для небольших Вью вполне можно ограничится функциями.
Конечно, что удобнее, то и используется!
template_ name можно и не передавать, если шаблон назвать соответственно (в данном случае women_list и women_detail) тогда джанга их автоматом найдет
Спасибо.
У меня эта шапка сайта с навигацией сразу работала на главной странице, это из за того что я сделал домашнее задание?
да
У меня почему то класс от CreateView работает только от класса формы которая непосредственно связана с моделью, с формами не связанными с моделью выдает ошибку type error 'BaseForm.__init__() got an unexpected keyword argument 'instance'' Сергей подскажите в чем проблема?
Вам лучше этот вопрос в сообщество в телеграм-канале задать, там быстро ответят!
Я так понял, что CreateView нужен именно для работы с формами связанными с моделями, а для форм не связанными с моделями нужно наследоваться от FormView???
аааааааа помогите!!!!!!!!!!!! да где же теперь у нас form в комментах, как мы в addpage.html получаем тот же результат, form это теперь какая переменная???? пожалуйста, что за нейминг, объясните как, очень прошу, задолбался уже((((((((
Я правильно понимаю что get_queryset он связан с ListView ?
Сорри за тупой вопрос! Разобрался)
@@kadyrkulove какой ответ на вопрос?
У меня одного возникает проблема, что статья при добавлении через пункт меню добавлении статьи не сохраняется? И если посмотреть в инструментах разработчика на вкладку network > headers, то оказывается при добавлении статьи у нас срабатывает метод GET, а не POST. И я так понимаю, что именно поэтому статья и не сохранилась.
Если добавлять статью через админку, то все ок.
Кто знает, как это можно исправить?
В теге form должен быть указан параметр method="POST".
спасибо, Сергей. Пол дня вчера не мог понять в чём проблема. Вроде и метод в теге форм указал ПОСТ... Оказалось банальная опечатка: вместо method = "POST", написал methodS="POST".
Спасибо за прекрасное изложение материала и за фит-бек, который Вы даёте😇
На 23:21 Как класс представления ShowPost понял, что нужно брать одну запись и именно с Шакирой (на которую нажали)? В функции представлении мы делали фильтрацию по слагу. А здесь как?
Автору вопроса, надеюсь, уже давно всё понятно, а тем, кому не понятно - по полю РК или слаг. ?В этом случае по слагу "тайтл" = имя героини? Через урлконф
Как нужно прописать форму в шаблоне? Так же как и раньше?
Спасибо вам за уроки. Очень внятно и подробно. Почему то при открывании поста через класс. Не хочет работать slug по какой-то причине конфликтует с pk.
С функцией все работает. Пользовательский слаг везде переименовал. На всякий случай удалил старые миграции, и заново сделал. Но все равно ругается на эти атрибуты(
Если сделать по pk, то начинает работать. Но странно, я же делаю слаг(
Это только detailview только проблема(
да, по умолчанию идентификатор в Django следует брать по атрибуту pk
@@selfedu_rus Но как переделать на слаг?)
@@AlexeyTeacher Я, вроде, там дальше показываю, как по слагу выбирать запись (если не в этом, то в другом уроке).
а если нужно передать пользователю вайл из (media) базы данных как download в вормати .txt как это лутше зделать?
Из БД или media? Это разные вещи. Вообще для скачивания каких-либо файлов можно создать специальную страницу с прикрепленным файлом. Например, можно посмотреть здесь snipp.ru/php/send-download (правда, там с использованием PHP, но принцип един).
@@selfedu_rus на фласке это было очень просто:
app.py - - - >
@app.route('/download_file', methods=['GET', 'POST'])
def download_file():
if 'userLogged' in session:
file_txt = "WebTools/Evaptray/example-input-evaporate.txt"
return send_file(file_txt, as_attachment=True)
return redirect(url_for('login'))
html - - - - >
Input file - example
на django хочетса реализовать кат что-бы admin заходил в админ панел, загружал "update.txt" и этот актуальный файл преподноситса затем для скачиванье на html странице.
@@vitali1959 Вот здесь можно посмотреть django.fun/tutorials/kak-zagruzit-fajly-s-django/
@@selfedu_rus Спасибо, Сергей! у меня все получилось.
media:
example-input-file.txt
views.py:
def download_csv(request):
file_path = os.path.join(settings.MEDIA_ROOT, 'example-input-file.txt')
if os.path.exists(file_path):
with open(file_path, 'rb') as fh:
response = HttpResponse(fh.read(), content_type="text/plain")
response['Content-Disposition'] = 'inline; filename=' + os.path.basename(file_path)
return response
urls.py:
path('download_csv/', views.download_csv, name='download_csv'),
download.html:
a href="{% url 'download_csv' %}" download=""
@@vitali1959 Круто, я даже сохранил ваш вариант, спасибо! )
Ох, как всё сложно. Спасибо за урок, как всегда очень подробно. А зачем вообще делать эти все представления, а не просто по конкретным URL выдавать нужные html страницы и в них выводить как и раньше? Так выглядит намного сложнее всё. В данный момент я разбираюсь с wagtail, там чуть проще, но нужно и простой джанго знать так же.
Выглядит сложнее по началу, но в последующем, если ты будешь писать большое веб-приложение, будет много головной боли если делать все «по простому»
Отлично !!!
Good man)
Доброго времени. У меня такой вопрос возник. Если у меня поле в моделе называется не slug, а url. В таком случае использование атрибута slug_url_kwarg(класса DetailView) выдает ошибку FieldError. Как быть? Поле переименовывать не хочется
Сам разобрался. Необходимо тогда прописать атрибут slug_field с нужным значением(в моем случае 'url'), а уже после него slug_url_kwarg с таким же значением
Может, кто-то сталкивался, вызывая self.cleaned_data['xxx'] при валидации поля формы, то данная запись удаляется из словаря, где её можно потом подобрать все облазил, в self.cleaned_data остаются другие записи, но ххх уже нет, а если мне эти данные нужны для ряда других проверок? Может быть как-то можно при первом вызове передать их ещё куда-то? Что-то ума не приложу, пол дня в пустую =(
Буду очень признателен за подсказку.
Добрый день, прошу подсказать, почему если я выбираю категорию которая не привязана ни к одному посту, то выпадает ошибка IndexError: list index out of range
, но если убрать
context['title'] = str(context['groups'][0].ng_gname)
context['group_select'] = context['groups'][0].ng_gname_id, то ошибка пропадает но, не работает выбранная категория и тайтл
Ну я уже детали реализации не помню. Думаю вам быстро помогут в сообществе телеграм-канала по Django. Ссылка под видео.
А как правильно указать в DetailView, если у меня так "/
slug_url_kwarg = 'post_cat'
slug_url_kwarg = 'post_slug'
Списком он не принимает.
Просто у меня получилось, если с такими двумя, да и с одним получается. Но хотелось бы ещё, чтоб если я менял название категории на другое, то выдавало бы ошибку 404, а не ту же новость.
👏👍
И django сам проверит если форма валидна? is_valid() спс за уроки, у вас самые топовые
да, в соответствии с настроенными валидаторами в модели формы
Просветите, как все строки закоментировать сразу?
выделяете в PyCharm и Ctrl + /