Заполнение Django данными по умолчанию

Андрей К…
Последнее изменение:
4
0
0

Допустим, у нас есть какое-то свойство, какого-то класса, которое мы хотим заполнять начальными значениями при развертывании Django с нуля на сервере или другой девелоперской машине.

Сегодня, например, у меня это ClientTypes модуля user_profile:

Я допускаю, что администратор со временем добавит какие-то виды клиентов, например «тестовый клиент», но все же хочу, чтобы при создании базы автоматически создавались типы клиентов «покупатель», «продавец», «покупатель и продавец». Сейчас, если забрать проект из git`а и выполнить миграции, нет ничего.

Что понадобится? Во-первых, давайте создадим свой пустой файл миграции, который будет вызываться среди прочих миграций:

python manage.py makemigrations user_profile empty


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

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

Давайте в этом файле создадим функцию, которая будет наполнять базу, и попросим Django её вызывать:

# Generated by Django 2.2.5 on 2019-12-28 10:07

# Добавляем models, чтобы Django могло создавать экземпляры нужных нам классов
from django.db import migrations, models

# Пишем функцию, которая будет вызываться при вызове этого файла миграции
# Название функции произвольное, должно принимать два параметра, как тут
def client_types(apps, schema_editor):
    # Типы - наш перечень, который будет вставлен в БД
    types = ["Покупатель", "Продавец", "Покупатель и продавец"]
    # Попросим Django вытащить модель - класс ClientTypes из аппликейшена user_profile
    ClientTypes = apps.get_model("user_profile", "ClientTypes")
    
    #Теперь в цикле создаём экземпляры класса с указанными параметрами и сохраняем их 
    for t in types:
        cl_type = ClientTypes(client_type=t)
        cl_type.save()

class Migration(migrations.Migration):

    dependencies = [
        ('user_profile', '0010_auto_20191105_1643'),
    ]

    # Тут вызываем встроенный метод RunPython и указываем, какую функцию вызвать при миграции (нашу)
    operations = [
        migrations.RunPython(client_types),
    ]

Написали, сохранили, теперь нужно её применить:

Заходим в админку, смотрим – данные появились

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

 

 

Комментарии: (4)
29.12.2019 07:15
Интересный способ. А почему не воспользоваться стандартными фикстурами? https://docs.djangoproject.com/en/3.0/howto/initial-data/ А потом если хочется загружать их при миграции можно вызвать стандартный loaddata из кода: https://docs.djangoproject.com/en/2.2/ref/django-admin/#running-management-commands-from-your-code
30.12.2019 06:36
Можно и так :) 
Миграции это тоже стандарный путь (по вашей первой ссылке - You can provide initial data with migrations or fixtures.)
В случае с миграциями можно на лету генерить данные, с фикстурами - нужно заранее сгененировать или выгрузить из базы.
Если бы речь шла о каталоге товаров, адресов доставки, каким-то иным большим набором данных, то фикстуры были более правильным выбором, конечно.
А там, где можно обойтись небольшим циклом, или сгенерировать что-то рандомное, или системно-зависимое (типа подставление хостнейма в какие-то поля), то уже миграции.
В любом случае спасибо за упоминание, без фикстур статья была точно неполной :)
06.01.2020 14:47
Чего-то как-то сложно. А вот так не проще?
models.py
........
STATUS_CHOICES = (
    ('new', 'Принят'),
    ('confirmed', 'Подтвержден'),
    ('processing','Обрабатывается'),
    ('sended','Отправлен'),
    ('canceled','Отменен')
    )

class Order(models.Model):
    name = models.CharField(verbose_name='Фамилия Имя Отчество', max_length=120, null=True)
    ...................
    status = models.CharField(max_length=64, choices=STATUS_CHOICES, default='new', verbose_name='Статус')
   .....................
07.01.2020 09:30
Хороший вариант, если опциями не нужно будет управлять через админку.
Пожалуйста, Авторизуйтесь что бы оставить свой комментарий