Создание проекта Django и импорт данных в БД. Создание проекта Django и импорт данных в БД. django import model

Создание проекта Django и импорт данных в БД.

Open in new window

Создание интернет-магазина штор.

В предыдущей части мы скопировали с сайта pangardin.com.ua каталог товаров и сохранили его в определенной структуре каталогов.

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

Для загрузки мы создадим команду import, которая будет запускаеться следующим образом:

./manage.py import

Создание проекта Django.

Создаем проект командой.

django-admin.py startproject prj

При этом создается новый каталог проекта в котором присутствует одноименный каталог с настройками проекта.

Переходим в каталог проекта.

cd prj

Создаем базу данных командой:

./manage.py migrate

При этом создается файл db.sqlite3 c таблицами приложений, которые поставляются с Django.

Создать приложение в проекте можно при помощи следующей команды.

./manage.py startapp shop

После выполнения этой команды будет создан новый каталог shop в папке проекта.

Далее нам необходимо добавить это приложение в список переменной INSTALLED_APPS в файле settings.py.

Таким образом мы включаем наше приложение в проект.

Заполним файл shop/models.py классами нашей модели.

from django.db import models
from django.utils.safestring import mark_safe

class Category(models.Model):
    ''' Категории  '''
    name = models.CharField(max_length=250)
    name_slug = models.CharField(max_length=250)


class Subcategory(models.Model):
    ''' Подкатегории  '''
    name = models.CharField(max_length=250)
    name_slug = models.CharField(max_length=250)
    category = models.ForeignKey(Category, on_delete=models.SET_NULL,  null=True)


class Good(models.Model):
    ''' Товары  '''
    name = models.CharField(max_length=250)
    name_slug = models.CharField(max_length=250)
    desc = models.TextField()
    subcategory = models.ForeignKey(Subcategory, on_delete=models.SET_NULL,  null=True)



class Image(models.Model):
    ''' Изображения  '''
    good = models.ForeignKey(Good, on_delete=models.SET_NULL, null=True)
    image = models.ImageField()

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

Таблицы связываются между собой специальным полем типа ForeignKey.

После того как все классы созданы, необходимо создать файл миграции командой:

./manage.py makemigrations

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

./manage.py migrate

После этого таблицы будут физически созданы.

Создание команды импорта.

При создании команды Django необходимо соблюсти требуемую структуру каталогов.

Внутри папки приложения shop необходимо создать каталог management и в нем каталог commands.

В каждый из этих двух каталогов необходимо поместить пустой файл init.py для того, чтобы обозначить их как пакеты Python.

Теперь внутри каталога commands создадим скрипт import.py который и будет нашей командой.

Для того чтобы написать команду нужно создать класс Command, унаследовав его от базового класса Django BaseCommand.

Затем необходимо переписать метод handle, который является точкой входа в команду.

from django.core.management.base import BaseCommand, CommandError

def import_catalog():
    pass

class Command(BaseCommand):
    def handle(self, *args, **options):
        print('Importing data')
        import_catalog()

Определим переменную с абсолютным путем к папке с данными.

DATA_DIR = os.path.join(BASE_DIR,'..','data','pangardin.com.ua')

После импорта классов модели мы в начале очистим все таблицы.

from shop.models import *

def import_catalog():
    Subcategory.objects.all().delete()
    Category.objects.all().delete()
    Good.objects.all().delete()
    Image.objects.all().delete()

И далее в цикле пройдем по подкаталогам и прочитаем содержимое файла meta.yml.

for item in os.listdir(DATA_DIR):
    if os.path.isdir(os.path.join(DATA_DIR,item)):
        # читаем meta.yml
        with open(os.path.join(DATA_DIR,item,'meta.yml'),'r') as f:
            rez = f.read()

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

pip install pyyaml

Далее в коде распарсим содержимое при помощи функции load().

yml_data = yaml.load(rez)

Теперь в переменной yml_data мы имеем словарь и можем обращаться к данным по ключу например так:

yml_data['name_ru']

Создадим категории в базе, исключая дубли.

# создаем категории в базе если такой нет
try: 
    cat = Category.objects.get(name_slug=yml_data['parent_slug'])
except:
    cat = Category()
    cat.name = yml_data['parent_name_ru']
    cat.name_slug = yml_data['parent_slug']
    cat.save()

Аналогичным образом поступим и с подкатегориями:

# создаем подкатегории в базе если такой нет
try: 
    scat = Subcategory.objects.get(name_slug=yml_data['name_slug'])
except:
    scat = Subcategory()
    scat.name = yml_data['name_ru']
    scat.name_slug = yml_data['name_slug']
    scat.category = cat
    scat.save()

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

for item_good in os.listdir(os.path.join(DATA_DIR,item)):
    if os.path.isdir(os.path.join(DATA_DIR,item,item_good)):
        import_goods(item_good,os.path.join(DATA_DIR,item),scat)

Делаем сохранение только если в цикл попадает каталог.

Опишем функцию сохранения товара.

def import_goods(name_slug,path,sub_category):
    print('Importing ..... %s' % name_slug)
    # читаем meta.yml
    try:
        with open(os.path.join(path,name_slug,'meta.yml'),'r') as f:
            rez = f.read()
    except:
        return False
    # парсим yml формат
    yml_data = yaml.load(rez) 
    # сохраняем позицию товара
    g = Good()
    g.name = yml_data['name_ru']
    g.name_slug = yml_data['name_slug']
    g.desc = yml_data['description_ru']
    g.subcategory = sub_category
    g.save()

В эту функцию передается транслитное название продукта, путь к каталогу категории и объект категории, в которой находится товар.

Other topics