Django
April 1

Создание Django проекта для новичка

Часть 1 - Подготовка

Установка Django:

pip install django

Создание нового проекта:

django-admin startproject myproject cd myproject

Создание нового приложения:

python manage.py startapp myapp

Добавление приложения в INSTALLED_APPS:

INSTALLED_APPS = [ ... 'myapp', ]

Создание моделей в myapp/models.py:

from django.db import models

class MyModel(models.Model): name = models.CharField(max_length=100) description = models.TextField()

Создание и применение миграций:

python manage.py makemigrations python manage.py migrate

Включаем админ панель admin.py должен выглядеть так:

from django.contrib import admin from .models import Post // Импортируем нашу модель

admin.site.register(Post)

Теперь у нас есть Django проект myproject в котором есть приложение myapp. По мимо этого у нас есть модель данных Post которая имеет два поля и мы провели ее миграции. Это значит мы можем по готовому шаблону помещать данные в базу данных которая уже есть в проекте. В конце мы подключили эту базу данных в админ панель, и теперь можем делать записи.

Часть 2 - Представления

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

Создание представления (View)

Откройте файл myapp/views.py и добавьте следующий код:

from django.shortcuts import render from .models import MyModel

def post_list(request): posts = MyModel.objects.all() # Получаем все записи из модели MyModel return render(request, 'myapp/post_list.html', {'posts': posts})

Тут мы получили все записи нашей модели, и возвращаем страницу post_list.html с данными posts которые несут в себе все записи. (Далее мы ее создадим)

Маршруты urls

Откройте или создайте файл myapp/urls.py и добавьте следующий код:

from django.urls import path from . import views

urlpatterns = [ path('', views.post_list, name='post_list'), ]

Тут мы говорим что если пользователь перейдет на страницу '', что по умолчанию главная, то сработает представление views.post_list. Можно сделать path('all_posts', views.post_list, name='post_list') // Тогда загружаться все будет не с site.ru, а с site.ru/all_posts

Откройте файл myproject/urls.py и импортируйте include:

from django.contrib import admin from django.urls import path, include

urlpatterns = [ path('admin/', admin.site.urls), path('', include('myapp.urls')), # Подключаем маршруты приложения myapp ]

С начала мы приложению сказали что открывать, теперь мы проекту скажем что если будет переход на '', - главную, мы обращаемся к urls приложения. А там мы уже написали какое представление запускать.

Создание шаблона

myapp/ templates/ myapp/ post_list.html

Создайте папку как показано выше и в ней еще одну папку. Важно смотрите за названиями, название папки - название приложения в котором ее создали. Templates всегда одно и то же, как в примере.

В настройках прописать путь как в примере:

TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [BASE_DIR / 'templates'], # Убедитесь, что путь указан правильно 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]

В файле post_list.html добавьте следующий код:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Посты</title> </head> <body> <h1>Список постов</h1> <ul> {% for post in posts %} <li> <strong>{{ post.name }}</strong><br> {{ post.description }} </li> {% endfor %} </ul> </body> </html>

Самое простое обращение к данным модели - это просто обратиться к ней через цикл так как в представлении мы передавали массив со всеми записями.

В общем этот гайд подсказка для меня самого. Буду дополнять

Часть 3 - бесконечность

linebreaks

При выводе текста, используй фильтр который сохранит в тесте абзацы заменив пустоту на <br>. Используй: {{ post.description|linebreaks }}

{{ post.content|linebreaks|truncatewords:"20" }}

Например тут мы с начала делаем абзацы, далее сокращаем до 20 слов текст.

ВАЖНО! СОЗДАЕМ ДЕТАЛЬНУЮ СТРАНИЦУ ЗАПИСИ С ПОЛНЫМ ЕЕ ТЕКСТОМ

Чтобы сделать так, чтобы пользователи могли перейти к полной записи и прочитать её полный текст, необходимо выполнить несколько шагов:

  1. Создать представление для отображения деталей записи.
  2. Создать URL для этого представления.
  3. Обновить шаблон для добавления ссылок на детали записи.

Откройте файл myapp/views.py и добавьте представление для отображения деталей записи:

from django.shortcuts import render, get_object_or_404 from .models import MyModel

def post_list(request): posts = MyModel.objects.all() return render(request, 'myapp/post_list.html', {'posts': posts})

def post_detail(request, pk): post = get_object_or_404(MyModel, pk=pk) return render(request, 'myapp/post_detail.html', {'post': post})

Тут get_object_or_404 получает данные модели Post только не всех записей а еще с pk=pk ее типа id.

Создание URL для представления деталей записи

Откройте файл myapp/urls.py и добавьте URL для нового представления:

from django.urls import path from . import views

urlpatterns = [ path('', views.post_list, name='post_list'), path('post/<int:pk>/', views.post_detail, name='post_detail'), # Добавляем URL для деталей записи ]

Тут говорим что если сработает страница /post/и любое число то сработает представление в котором мы получим запись с pk= числу. Например site.ru/post/4 - будет искать 4-ую запись в модели post

Создайте новый файл myapp/templates/myapp/post_detail.html и добавьте в него следующий код:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{{ post.name }}</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"> <style> body { font-family: Arial, sans-serif; line-height: 1.6; margin: 20px; } h1 { color: #333; } .post-detail { max-width: 800px; margin: 0 auto; } .post-header { margin-bottom: 20px; } .post-content { margin-bottom: 20px; } .back-link { display: inline-block; margin-top: 20px; } </style> </head> <body> <div class="post-detail"> <div class="post-header"> <h1>{{ post.name }}</h1> <small class="text-muted">{{ post.date_posted }}</small> </div> <div class="post-content"> <p>{{ post.description|linebreaks }}</p> </div> <div class="back-link"> <a href="{% url 'post_list' %}" class="btn btn-secondary">Назад к списку постов</a> </div> </div> </body> </html>

Вот простой пример как можно вывести полные данные в шаблон post_detail.html

Получаем все записи из модели Post от новых к старым

posts = Post.objects.all().order_by('-date_posted') 

ДЕЛАЕМ РЕЙТИНГ У ЗАПИСЕЙ

В моделях добавим новое поле

rating = models.IntegerField(default=0)

И проведем миграции

Далее добавим в файл views новые представления

def upvote(request, pk): obj = get_object_or_404(MyModel, pk=pk) obj.rating += 1 obj.save() return redirect('post_detail', pk=pk)

def downvote(request, pk): obj = get_object_or_404(MyModel, pk=pk) obj.rating -= 1 obj.save() return redirect('post_detail', pk=pk)

Наш urls приложения теперь такой:

from django.urls import path from . import views

urlpatterns = [ path('', views.post_list, name='post_list'), path('post/<int:pk>/', views.post_detail, name='post_detail'), path('post/<int:pk>/upvote/', views.upvote, name='upvote'), path('post/<int:pk>/downvote/', views.downvote, name='downvote'),

]

Теперь мы можем в шаблоне вызвать

<b>Рейтинг: {{ post.rating }}</b>

А в файл с деталями записи можно вставить:

<p><b>Рейтинг: {{ post.rating }}</b></p> <br> <!-- Отдельные ссылки для голосования --> <a href="{% url 'upvote' post.pk %}" class="btn btn-success me-2 btn-sm">

<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-hand-thumbs-up" viewBox="0 0 16 16"> <path d="err"/> </svg> Нравиться </a> <a href="{% url 'downvote' post.pk %}" class="btn btn-danger btn-sm"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-hand-thumbs-down" viewBox="0 0 16 16"> <path d="err"/> </svg> Не нравиться </a>

Собственно кнопки:

{% url 'upvote' post.pk %}

{% url 'downvote' post.pk %}