Django 5 для начинающих

Прогресс по курсу:  9/1004

5.2 Создание моделей данных блога
4 из 9 шагов пройдено
0 из 21 баллa  получено

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

Теперь, когда есть модель постов блога, необходимо создать соответствующую таблицу базы данных.

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

Команда migrate применяет миграции ко всем приложениям, перечисленным в INSTALLED_APPS. Она синхронизирует базу данных с текущими моделями и существующими миграциями.

Прежде всего необходимо создать первоначальную миграцию модели Post. Выполните следующую ниже команду в командной оболочке из корневого каталога своего проекта:

python manage.py makemigrations blog

Вы должны получить результат, аналогичный приведенному ниже:

(venv) PS D:\Project\mysite> python manage.py makemigrations blog 
Migrations for 'blog':
  blog\migrations\0001_initial.py
    - Create model Post

Внутри каталога миграций приложения blog Django только что создал файл 0001_initial.py.

Эта миграция содержит инструкции SQL по созданию таблицы базы данных для модели Post и определения индекса базы данных для поля publish.

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

Давайте взглянем на исходный код SQL, который Django исполнит в базе данных, чтобы создать таблицы вашей модели.
Команда sqlmigrate принимает имена миграций и возвращает их SQL без его исполнения.

Выполните следующую ниже команду из командной оболочки, чтобы проинспектировать результирующий исходный код SQL вашей первой миграции:

python manage.py sqlmigrate blog 0001

Результат должен выглядеть вот так:

BEGIN;

--

-- Create model Post --

CREATE TABLE "blog_post" (

"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"title" varchar(250) NOT NULL,
"slug" varchar(250) NOT NULL,
"body" text NOT NULL,
"publish" datetime NOT NULL,
"created" datetime NOT NULL,
"updated" datetime NOT NULL,
"status" varchar(2) NOT NULL,
"author_id" integer NOT NULL REFERENCES "auth_user" ("id") DEFERRABLE INITIALLY DEFERRED);

--

-- Create blog_post_publish_bb7600_idx on field(s) -publish of model post --

CREATE INDEX "blog_post_publish_bb7600_idx" ON "blog_post" ("publish" DESC);
CREATE INDEX "blog_post_author_id_dd7a8485" ON "blog_post" ("author_id");
COMMIT;

Точный результат зависит от используемой вами базы данных.
Приведенный выше результат сгенерирован для SQLite.

Из полученного результата видно, что Django генерирует имена таблиц, комбинируя имя приложения с именем модели, обозначенной в нижнем регистре blog_post.

Кроме того, существует возможность указывать своей модели имя конкретно-прикладной базы данных.
Это делается в Meta классе модели при помощи атрибута db_table.

Django создает автоинкрементный столбец id, используемый в каждой модели в качестве первичного ключа, указав primary_key=True в одном из полей модели, но это поведение можно тоже переопределять.

Столбец id состоит из автоматически увеличивающегося целого числа. Этот столбец соответствует полю id, которое добавляется в модель автоматически.

Создаются следующие два индекса базы данных:

  • индекс в убывающем порядке по столбцу publish. Мы определили этот индекс явным образом с помощью опции indexes Meta класса модели;

  • индекс по столбцу author_id, поскольку поля типа ForeignKey по умолчанию подразумевают индекс.

Давайте сравним модель Post с соответствующей ей таблицей blog_post базы данных:

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

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

python manage.py migrate

Вы получите результат, который заканчивается следующей ниже строкой:

Applying blog.0001_initial... OK

Мы только что применили миграции приложений, перечисленных в INSTALLED_APPS, включая приложение blog.

После применения миграций база данных отражает текущее состояние моделей.

Если вы внесете в файл models.py любые правки, чтобы добавить, удалить либо изменить поля существующих моделей, либо добавите новые модели, то вам придется создать новые миграции, снова применив команду makemigrations.

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


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

местами не хватало именно такой теории, как в этом разделе, где каждая буква расписана и везде объяснения что и почему, спасибо

Создаются следующие два индекса базы данных:

Создаются следующие три индекса базы данных:

@Garry_Veles, спасибо, исправил.

вывод отличается! база SQLite! этого у меня нет 

  • индекс по столбцу slug, поскольку поля типа SlugField по умолчанию подразумевают индекс;



BEGIN;
--
-- Create model Post
--
CREATE TABLE "blog_post" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "title" varchar(250) NOT NULL, "slug" varchar(250) NOT NULL UNIQUE, "body" text NOT NULL, "publish" datetime NOT NULL, "created" datetime NOT NULL, "updated" datetime NOT NULL, "status" varchar(2) NOT NULL, "author_id" integer NOT NULL REFERENCES "auth_user" ("id") DEFERRABLE INITIALLY DEFERRED);
CREATE INDEX "blog_post_author_id_dd7a8485" ON "blog_post" ("author_id");
CREATE INDEX "blog_post_publish_bb7600_idx" ON "blog_post" ("publish" DESC);
COMMIT;



вот модель!

from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User


class Post(models.Model):
    class Status(models.TextChoices):
        DRAFT = 'DF', 'Draft'
        PUBLISHED = 'PB', 'Published'

    title = models.CharField(max_length=250)
    slug = models.SlugField(max_length=250, unique=True)
    author = models.ForeignKey(User,
                               on_delete=models.CASCADE,
                               related_name='blog_posts')

    body = models.TextField()

    publish = models.DateTimeField(default=timezone.now)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    status = models.CharField(max_length=2,
                              choices=Status.choices,
                              default=Status.DRAFT)

    class Meta:
        ordering = ['-publish']
        indexes = [
            models.Index(fields=['-publish']),
        ]

    def __str__(self):
        return self.title
Изменен No Name

@No_Name, все таки индекс в таблице базы данных SQLite не создан я хз почему так как перепробовал уже все по этому я его сам создал в нашей таблицы пример ниже!

class Meta:
    ordering = ['-publish']
    indexes = [
        models.Index(fields=['-publish']),
        models.Index(fields=['slug']),
    ]

так же в БД вы можете проверить что индекс создан с помощью команды :

sqlite> PRAGMA index_list('blog_post');

вывод 

seq  name                          unique  origin  partial

---  ----------------------------  ------  ------  -------

0    blog_post_slug_cdb902_idx     0       c       0      

1    blog_post_publish_bb7600_idx  0       c       0      

2    blog_post_author_id_dd7a8485  0       c       0      

3    sqlite_autoindex_blog_post_1  1       u       0      

sqlite> 


если добавить индекс самому и потом использовать команду 

python3 manage.py sqlmigrate blog 0001

он все равно не будет отображен лол 🤣  по этому лучше всего смотреть сразу в БД я пользуюсь БД через терминал так проще всего


если автор увидит это смс думаю он объяснит почему так выходит

@No_Name, Скорее всего у вас в коде что то, видимо вы загрузили немного другой код для модели потому что при добавлении индекса в модель в коде который пойдет в БД есть индекс! 

 

from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User


class Post(models.Model):
    class Status(models.TextChoices):
        DRAFT = 'DF', 'Draft'
        PUBLISHED = 'PB', 'Published'

    title = models.CharField(max_length=250)
    slug = models.SlugField(max_length=250, unique=True)
    author = models.ForeignKey(User,
                               on_delete=models.CASCADE,
                               related_name='blog_posts')

    body = models.TextField()

    publish = models.DateTimeField(default=timezone.now)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    status = models.CharField(max_length=2,
                              choices=Status.choices,
                              default=Status.DRAFT)

    class Meta:
        ordering = ['-publish']
        indexes = [
            models.Index(fields=['-publish']),
            models.Index(fields=['slug']),
        ]

    def __str__(self):
        return self.title

При такой вот модели код запроса как у вас в лекции!

BEGIN;
--
-- Create model Post
--
CREATE TABLE "blog_post" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "title" varchar(250) NOT NULL, "slug" varchar(250) NOT NULL UNIQUE, "body" text NOT NULL, "publish" datetime NOT NULL, "created" datetime NOT NULL, "updated" datetime NOT NULL, "status" varchar(2) NOT NULL, "author_id" integer NOT NULL REFERENCES "auth_user" ("id") DEFERRABLE INITIALLY DEFERRED);
CREATE INDEX "blog_post_author_id_dd7a8485" ON "blog_post" ("author_id");
CREATE INDEX "blog_post_publish_bb7600_idx" ON "blog_post" ("publish" DESC);
CREATE INDEX "blog_post_slug_cdb902_idx" ON "blog_post" ("slug");
COMMIT;



@No_Name, Разобрался, документация как раз и говорит о том, что у полей SlugField автоматически добавляется индекс. Но по совету одного учащегося мы добавили unique=True к этому полю, с таким параметром Django больше не создает индексы для SlugField.

Убрал из лекции лишнее по индексам.

Изменен Илья Перминов

@Илья_Перминов, Это больше моя ошибка, так как я знаю за unique=True и когда его убрал то забыл в команде python3 manage.py sqlmigrate blog 0001 изменить 1 на 2 так как создалась новая миграция python3 manage.py sqlmigrate blog 0002 и по этому пришлось самому вписывать уже в метаданные этот индекс 

 

class Meta:
        ordering = ['-publish']
        indexes = [
            models.Index(fields=['-publish']),
            models.Index(fields=['slug']),
        ]


так же при наборе команды python3 manage.py sqlmigrate blog 0001 в выводе джанго ничего опять же не было но в БД все уже было сделано вот я и закинул и списал на то что глюк в версии джанго так как есть вопросы по ядре нашел статьи, но потом через пару часов понял где ошибся и уже разобрался, спасибо что ответили сейчас все проверил все гуд! Внимательность наше все не раз уже сталкиваюсь с тем что надо быть ну очень внимательным!

Курс огонь!

Здесь у status длина 10, но в модели max_length=2

@Дмитрий_Чекмасов, Спасибо, исправил.