Премиум каналы

Код на салфетке

Канал для тех, кому интересно программирование на Python и не только, процесс создания сайта на Django с нуля, создание Telegram-бота, ну и просто кто желает расширять кругозор в компании таких же жаждущих знаний.

Последние публикации с канала

Вчерашняя задача на внимательность оказалась под силу только 33% ответивших, что, если честно, удивило нас. Наибольшим сюрпризом стал самый популярный ответ, набравший 54% голосов, потому что он же и самый невозможный из всех. Давайте разберёмся.

Код задачи:

z = 0
for i in range(1, 10):
if (i + 1 // 2) % 7 == 0:
break
else:
z += int(i % 2 == 0)
print(z, end='')
else:
print('end')


Цикл for-else.
Первым делом давайте вспомним как работает цикл for.

При объявлении цикла мы задаём итерируемую переменную (чаще всего это i, но не забывайте о читаемости кода, называйте переменные понятными словами!), а также сам итератор. Им может быть range(от, до) или список элементов, например, [1, 2, 3, 4, 5].

Цикл будет выполняться до тех пор, пока ему есть, по чему итерироваться, или пока он не будет остановлен. Для остановки цикла используется оператор break.

У циклов есть и ещё один необязательный блок - else. Он срабатывает только тогда, когда цикл закончил свою работу без остановок. Именно поэтому ответ 112233end никак не мог появиться, поскольку в основном блоке цикла происходит его остановка оператором break.

Разбор задачи.
Вернёмся к задаче и разберём процесс выполнения по порядку.

Определяем переменную z со значением 0.

Далее запускается цикл, перебирающий цифры от 1 до 10 (до 9 включительно).
В цикле находится условие:
- Если результат суммы целочисленного деления 1 на 2 со значением i кратно семи - останавливаем цикл. Обратите внимание, что 1 // 2 всегда будет давать 0, его можно игнорировать.
- Иначе к переменной z прибавляем преобразованный к числу результат проверки чётености числа в переменной i. И выводим значение z без переноса строки.

В таком случае у нас происходит всего 7 итераций цикла:
1. z=0, i=1. 1 кратно 7-ми? Нет. 1 чётное? Нет. К переменной z прибавляем 0 (потому что "False" - это и есть 0 в мире целых чисел) и выводим 0.
2. z=0, i=2, print=0. 2 кратно 7-ми? Нет. 2 чётное? Да. К переменной z прибавляем 1 (потому что "True" - это и есть 1 в мире целых чисел) и выводим 1.
3. z=1, i=3, print=01. 3 кратно 7-ми? Нет. 3 чётное? Нет. К переменной z прибавляем 0 и выводим 1.
4. z=1, i=4, print=011. 4 кратно 7-ми? Нет. 4 чётное? Да. К переменной z прибавляем 1 и выводим 2.
5. z=2, i=5, print=0112. 5 кратно 7-ми? Нет. 5 чётное? Нет. К переменной z прибавляем 0 и выводим 2.
6. z=2, i=6, print=01122. 6 кратно 7-ми? Нет. 6 чётное? Да. К переменной z прибавляем 1 и выводим 3.
7. z=3, i=7, print=011223. 7 кратно 7-ми? Да. Останавливаем цикл.

28.04.2024 / 10:04
27.04.2024 / 07:04

Что выведет код с изображения ниже? №19

Anonymous Quiz

31% - 011223

14% - 001122

7% - 112233

48% - 112233end

27.04.2024 / 07:04

Приветствую!

Добро пожаловать на вечерний пятничный просмотр фильма! Сегодня вечером мы собрались здесь, чтобы насладиться увлекательным и захватывающим кинематографическим произведением. Вместе мы погрузимся в другие миры, переживем приключения и почувствуем всю палитру эмоций, которые кино может подарить. Приготовьтесь к незабываемому вечеру, полному сюрпризов и волнения. Погрузитесь в красочный мир кино и насладитесь каждым моментом.

Фильм: Книга Илая

Год: 2010

После вселенской катастрофы Америка превратилась в выжженную пустыню. По бескрайним дорогам, кишащим бандами, враждующими между собой за воду и еду, странствует мудрый Илай. Однажды он прибывает в мрачные края, где когда-то была цветущая Калифорния, а теперь это сущий ад, где бесчинствует тиран Карнеги.

https://www.sspoisk.ru/film/424266/

Приятного просмотра!

26.04.2024 / 14:04

Опоздав на недельку, вчера мы опубликовали очередную субботнюю задачу. Задача весьма простая, но требует внимательности 😉

Код задачи:

lst = [i ** 2 for i in range(10)]
lst = filter(lambda x: x % 2 == 0, lst)
print(list(lst)[::2])


**Разбор задачи.**
Пропустим часть, в которой описываются действия, и сразу перейдём к разбору.

В самом начале мы создаём переменную lst, в которой при помощи list comprehension (лист компрехеншен) создаём список квадратов чисел от 0 до 9. В итоге получаем следующий список:
lst = [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]


Далее мы в эту же переменную lst помещаем результат работы функции filter(). Данная функция, как понятно из названия, "фильтрует" проходящий через неё список или кортеж, создавая на выходе итератор с подходящими по условию элементами. В качестве условия filter() принимает функцию возвращающую True или False.

В нашем случае, в качестве функции мы передаём анонимную lambda-функцию, которая проверяет, является ли число из списка lst чётным или нет. В итоге имеем следующий результат:
lst = [0, 4, 16, 36, 64]


В конце при помощи функции print() мы выводим преобразованный в список итератор на экран. При этом мы используем срез, выводящий каждый второй элемент (начиная с нулевого).

Получаем:
>>> [0, 16, 64]

21.04.2024 / 07:04
20.04.2024 / 12:04

Что выведет код с изображения ниже?

Anonymous Quiz

14% - [64, 36, 16, 4, 0]

44% - [0, 16, 64]

31% - [4, 36]

11% - [36, 4]

20.04.2024 / 12:04

Дорогие друзья,

С наступлением пятницы настает время, когда мы можем отдохнуть от забот и насладиться вечером в уюте своего дома. И что может быть лучше, чем уютно устроиться на диване с чашкой горячего чая или вкусным попкорном и наслаждаться просмотром любимого фильма?

Приготовьтесь окунуться в мир кино и погрузиться в историю, которая захватит вас с первых минут. Забудьте обо всех повседневных проблемах и наслаждайтесь вечером, полным эмоций, смеха и волнения.

Фильм: Апгрейд

Год: 2018

В недалеком будущем технологии контролируют все процессы жизни человечества. Когда технофоб Грей теряет в результате нападения банды отморозков жену, а сам оказывается парализованным, его единственной надеждой на отмщение становится новейшая научная разработка. Экспериментальный имплант «стем» не только ставит Грея на ноги, но наделяет его суперсовременным кибер-мозгом и сверхчеловеческими способностями.

https://www.sspoisk.ru/film/1009784/

Приятного просмотра и отличного вечера, друзья!

19.04.2024 / 14:04

Forwarded From Заметки на салфетке

Всем привет!

Уже в эту субботу, 20го апреля состоится финальное демо проектов на стажировке в LAD Academy.

Почти шесть месяцев ушло на разработку MVP проекта LAPA.

Приглашаю всех желающих на нашу презентацию.

Мероприятие пройдёт в Google Meet. Начало в 10:00 по МСК и до 17-ти часов.
Презентация проекта LAPA запланировано на 11:45-12:30.

Ссылка на мероприятие: https://meet.google.com/zhv-kmcb-ros

P.S. Пост про стажировку будет, как только разберусь с делами)

18.04.2024 / 07:04

Рад снова приветствовать вас, друзья!

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

Фильм: Кон-Тики

Год: 2012

Это известная история о том, как норвежский путешественник Тур Хейердал в 1947 году пересёк Тихий океан от Перу до Полинезии на бальсовом плоту. Таким способом он хотел доказать свою теорию о заселении Полинезии из Южной Америки, а не из Азии, как тогда считалось.

https://www.kinopoisk.ru/film/506432/

https://www.sspoisk.ru/film/506432/

Приятного просмотра и отдыха!

12.04.2024 / 14:04

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

Код задачи:

lst = [1]
lst1 = lst * 0
lst2 = lst * 1

print(lst[0] == lst2[0], lst[0] is lst2[0], lst[0] == lst1[0])


Разбор задачи:
Создаём три переменные:
- lst - список с одним элементом.
- lst1 - умноженный на ноль список lst.
- lst2 - умноженный на один список lst.

Затем в функции print() выводим три проверки:
- Сравнение нулевого элемента в списках lst и lst2.
- Проверку на то, что нулевой элемент в списке lst идентичен нулевому элементу из списка lst2.
- Сравнение нулевого элемента в списках lst и lst1.

Где подвох?
В общем и целом задача подходит под разбор, написанный для 15-й задачи, с одним лишь исключением.

При создании переменных мы использовали умножение списка, и если при умножении на единицу список останется неизменным, то при умножении на ноль он просто "очистится".
Подвох именно в этом. После того, как мы умножили список lst = [1] на ноль, мы получили пустой список []. Следовательно, все попытки получить какой-либо элемент списка будут вызывать исключение IndexError.

08.04.2024 / 10:04
06.04.2024 / 15:04

Что выведет код с изображения ниже? №17

Anonymous Quiz

8% - True, True, True,

28% - True, True, False

18% - True, False, False

13% - False, False, True

33% - Ничего из перечисленного выше

06.04.2024 / 15:04

Добрый вечер, друзья!

Пятница - время для отдыха и развлечений. Подготовьте уютное место, закуски и напитки, чтобы создать атмосферу настоящего кинотеатра прямо у себя дома. Готовьтесь к запредельным приключениям и не забудьте приглушить свет - ведь именно в темноте ужасы кажутся еще более реальными. Наслаждайтесь вечером и пусть этот фильм подарит вам заряд адреналина на целую неделю!

Фильм: Зеркала

Год: 2008

Бывший нью-йоркский полицейский устраивается на работу ночным сторожем выгоревших руин крупного универмага. Обходя обугленные развалины, он начинает замечать что-то зловещее в декоративных зеркалах, украшающих стены: в огромных мерцающих стёклах отражается что-то жуткое.

https://www.sspoisk.ru/film/263447/

Приятного просмотра!

05.04.2024 / 14:04

Forwarded From Заметки на салфетке

Всем привет!

За несколько дней произошло несколько событий.

Начнём с главного.

19-го января у моей группы в GB прошла итоговая аттестация (защита диплома). Нам обещали в течении месяца выслать диплом и номер его отслеживания... Видимо в GB месяц длится иначе, т.к. диплом я и мои одногруппники начали получать только с этой недели... Получив оповещение от Почты России о прибытии письма. 2.5 месяца на изготовление, отправки, но прикол не в этом! Теперь они предоставляют дипломы в виде двух листочков, без корочки. Ну да ладно, я уже на WB выбрал обложку)

И вот казалось бы, диплом, наконец-то эпопея длительностью в 1.5 года + 2.5 месяца ожидания диплома подошли к концу, надо радоваться... А радости то нет. И ощущения "дипломированного специалиста" тоже. Такие дела.

Второе "событие", опишу позже. там тоже есть приколы)

05.04.2024 / 07:04

Добавить комментарии несложно. Куда сложнее будет далее за ними следить. Хоть у нас и есть "защита" в виде ограничения на зарегистрированных пользователей, спамеры "не дремлют", и, возможно, в будущем придётся добавлять защиту в виде капчи или что-то другое.



Файлы к посту, можно получить в боте по коду: 279348

Пост на сайте
Поддержать проект

#Python #Django #Гайды #Модели #Представления #Формы #Комментарии

03.04.2024 / 12:04

<div class="row">
<h2 class="mt-3 mb-3">Добавить комментарий:</h2>
{% if user.is_authenticated %}
<form method="post" enctype="multipart/form-data" action="{% url "blog:add_comment" pk=post.pk %}">
{% csrf_token %}
{{ comment_form.comment }}
<button class="btn btn-outline-warning mt-3" type="submit">Отправить</button>
</form>
{% else %}
<p><a href="{% url 'user_app:login' %}">Войдите</a> чтобы добавить комментарий.</p>
{% endif %}
</div>

<div class="row">
<h2 class="mt-3 mb-3">Комментарии пользователей:</h2>
{% if comments %}
{% for comment in comments %}
<p><a href="{% url 'user_app:user_profile' username=post.author %}">{{ comment.user }}</a>
| {{ comment.created_at }} | {% if comment.user user or user.is_superuser %}
<a href="{% url 'blog:edit_comment' comment.pk %}">Редактировать</a> |
<a href="{% url 'blog:delete_comment' comment.pk %}">Удалить</a>
{% endif %}</p>
<p>{{ comment.comment }}</p>
<hr>
{% endfor %}
{% else %}
<p>Нет комментариев</p>
{% endif %}
</div>

В первом блоке выводим форму для добавления комментария. Обратите внимание, что в форме передаём аргумент action с маршрутом на представление добавления комментария.

Во втором блоке в цикле выводим комментарии. Также проверяем, что автор комментария – это текущий пользователь или администратор, чтобы отобразить кнопки для редактирования и удаления комментария.

Далее откроем шаблон страницы поста и в удобное место подключим файл шаблона комментариев, передав в него объект поста и список комментариев:


{% include "blog/modules/comments.html" with post=post comments=post.comments.all%}


Шаблон редактирования комментария.
Создадим файл comment_edit.html и пропишем следующий код:


{% extends 'blog/base.html' %}
{% block title %}Редактирование комментария{% endblock %}

{% block content %}
<div class="form-section container mt-3">
<h2>Редактирование комментария</h2>
<form method="post">
{% csrf_token %}
<p>{{ form.comment }}</p>
<button class="btn btn-primary" type="submit">Обновить</button>
<a href="{% url 'blog:post_page' slug=object.post.slug category_slug=object.post.category.slug %}"
class="btn btn-secondary">Отмена</a>
</form>
</div>
{% endblock %}


Шаблон удаления комментария.
Создадим файл comment_delete.html и пропишем следующий код:


{% extends 'blog/base.html' %}
{% block title %}Удаление комментария{% endblock %}

{% block content %}
<div class="form-section container mt-3">
<h2>Удаление комментария</h2>
<p>Вы действительно хотите удалить этот комментарий?</p>
<pre>{{ object.comment }}</pre>
<form method="post">
{% csrf_token %}
<button class="btn btn-danger me-2" type="submit">Да, удалить</button>
<a href="{% url 'blog:post_page' slug=object.post.slug category_slug=object.post.category.slug %}"
class="btn btn-secondary">Отмена</a>
</form>
</div>
{% endblock %}


Заключение.

03.04.2024 / 12:04

def get_context_data(self, **kwargs):  
context = super().get_context_data(**kwargs)
context["comment_form"] = CommentForm()
return context


Базовое представление.
Нам понадобится три представления, и по сути они идентичны. Различия только в наследуемых классах, поэтому, чтобы избежать дублирования кода, создадим базовый класс BaseCommentView.

В классе пропишем поле model, в котором определим класс модели комментария.

И переопределим метод get_success_url, принимающий только self.
В нём мы вернём путь до страницы поста.


Код класса:

class BaseCommentView:  
model = CommentModel

def get_success_url(self):
post = models.PostModel.objects.get(pk=self.object.post.pk)
return reverse(
"blog:post_page",
kwargs={"category_slug": post.category.slug, "slug": post.slug},
)


Представление добавления комментария.
Создадим класс AddCommentView, унаследованный от BaseCommentView и CreateView, который будет отвечать за добавление комментария.

В нём мы добавим поле form_class, определив в нём класс формы.

И переопределим метод form_valid, принимающий self и объект формы form.
Поскольку в модель класса требуется передавать пользователя и связанный с комментарием пост, а в форме мы не можем этого сделать, определим их тут.
Внутри метода определяем поля user и post, затем вызываем super-метод для сохранения объекта.


Код представления:

class AddCommentView(BaseCommentView, CreateView):  
form_class = CommentForm

def form_valid(self, form):
form.instance.user = self.request.user
form.instance.post = models.PostModel.objects.get(pk=self.kwargs.get("pk"))
return super().form_valid(form)


Представления редактирования и удаления комментария.
Создадим два класса:

- EditCommentView, унаследованный от BaseCommentView и UpdateView.
- DeleteCommentView, унаследованный от BaseCommentView и DeleteView.


В обоих классах пропишем поле template_name, в котором пропишем шаблон для страницы редактирования и страницы удаления комментария.

В классе EditCommentView дополнительно пропишем поле form_class, как в классе добавления комментария.


Код классов:

class EditCommentView(BaseCommentView, UpdateView):  
form_class = CommentForm
template_name = "blog/comment_edit.html"


class DeleteCommentView(BaseCommentView, DeleteView):
template_name = "blog/comment_delete.html"


Маршруты представлений.
Для всех трёх представлений осталось создать маршруты. Для этого откроем файл urls.py и в список urlpatterns добавим следующие строки:


path("comment/add/<int:pk>/", views.AddCommentView.as_view(), name="add_comment"),  
path(
"comment/edit/<int:pk>/", views.EditCommentView.as_view(), name="edit_comment"
),
path(
"comment/delete/<int:pk>/",
views.DeleteCommentView.as_view(),
name="delete_comment",
),


Шаблоны комментариев.
Начнём с основного шаблона вывода комментариев.


Шаблон добавления и вывода комментариев.
В директории с шаблонами создадим новый файл comments.html.

В нём пропишем шаблон для отображения комментариев:

03.04.2024 / 12:04

- comment – Текстовое поле для комментария.
- created_at – Поле с датой написания комментария.


Также пропишем внутренний класс Meta с названием модели и dunder-метод __str__ с текстовым представлением объекта модели.


Код модели:

class CommentModel(models.Model):  
user = models.ForeignKey(
User, on_delete=models.CASCADE, verbose_name="Пользователь"
)
post = models.ForeignKey(
PostModel,
on_delete=models.CASCADE,
verbose_name="Пост",
related_name="comments",
)
comment = models.TextField(verbose_name="Комментарий")
created_at = models.DateTimeField(auto_now_add=True)

class Meta:
verbose_name = "Комментарий"
verbose_name_plural = "Комментарии"

def __str__(self):
return f"Комментарий от {self.user} к посту {self.post}"


Регистрация в панели администратора.
Откроем файл admin.py.

Создадим класс CommentAdmin, унаследованный от admin.ModelAdmin. Обернём его в декоратор @admin.register(), передав в качестве аргумента модель комментария.

Внутри класса поля можно прописать по желанию, например:

- list_display - отображаемые столбцы.
- list_filter - выбор по каким полям проводить фильтрацию.


Дополнительно добавим столбец с названием поста при клике на которую будет открываться страница поста.

Для этого создадим метод post_link, в аргументах он принимает self и объект модели obj.
Внутри метода, используя функцию mark_safe, возвращаем строку со ссылкой.

Затем ниже вызываем метод allow_tags и устанавливаем его в True. Это позволит выводить HTML на странице панели администратора.

Не забываем прописать новое поле в list_display.


Код класса:

@admin.register(models.CommentModel)  
class CommentAdmin(admin.ModelAdmin):
list_display = ("user", "post_link", "created_at", "comment")
list_filter = ("user", "post")

def post_link(self, obj):
return mark_safe(
f'<a href="{obj.post.get_absolute_url()}">{obj.post.title}</a>'
)

post_link.allow_tags = True


Форма добавления комментария.
Для того чтобы можно было добавлять новый комментарий, необходима форма модели.

Откроем файл forms.py и создадим класс CommentForm, унаследованный от forms.ModelForm.

Форма будет весьма классическая:

- Определяем поле comment.
- Прописываем класс Meta, указав модель и всего одно поле - comment.



Код формы:

class CommentForm(forms.ModelForm):  
comment = forms.CharField(
widget=forms.Textarea(
attrs={
"class": "form-control",
"placeholder": "Введите текст комментария",
"rows": 5
}
),
)

class Meta:
model = CommentModel
fields = ("comment",)


Представления.
Теперь займёмся представлениями. Нам для комментариев нужно три представления:

- Добавление комментария.
- Редактирование.
- Удаление.


Также необходимо изменить представление страницы поста для передачи в него формы комментария.


Представление страницы поста.
Откроем файл views.py. Найдём класс PostPageView и добавим метод get_context_data.
Он тоже весьма стандартный. Внутри метода в контекст добавим новый ключ comment_form, в который определим объект формы CommentForm.


Код метода:

03.04.2024 / 12:04

Django 41. Комментарии к постам
Автор: Иван Ашихмин

В нашем проекте не хватает одного важного элемента – блока комментариев на странице поста. Давайте исправим это.

Что мы сделаем:

- Добавим на страницу поста отображение комментариев.
- Добавим возможность авторизованным пользователям оставлять комментарии.
- Также у автора комментария или администратора должна быть возможность удалить или отредактировать комментарий.



Модель комментария.
Для хранения комментариев нам нужна модель.

Откроем файл models.py в директории приложения blog.

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

- user – Внешний ключ на модель пользователя.
- post – Внешний ключ на модель поста. Для доступа к модели комментария из объекта модели поста указываем аргумент related_name="comments".

03.04.2024 / 12:04
Отзывы: - 0
Поделитесь вашим мнением! Оставьте отзыв:

Похожие

Избранное