Импорт данных в модель Django из csv-файлов

Обработка и анализ файлов формата CSV (comma separated values -значения, разделенные запятыми) с использованием Python и Django позволят использовать новый способ использования данных в вашем проекте. Концепция довольно проста, поскольку файл CSV настолько распространен и очень легко разбирается в Python. Ниже приведен пример реализации использования модели Django с файлом csv.

Models.py ( yourapp.models.py)

from __future__ import unicode_literals
import csv
import io
from django.conf import settings
from django.db import models
from django.db.models.signals import post_save, pre_save
from django.utils.text import slugify

from yourapp.signals import csv_uploaded
from yourapp.validators import csv_file_validator

def upload_csv_file(instance, filename):
    qs = instance.__class__.objects.filter(user=instance.user)
    if qs.exists():
        num_ = qs.last().id + 1
    else:
        num_ = 1
    return f'csv/{num_}/{instance.user.username}/{filename}'

class CSVUpload(models.Model):
    user        = models.ForeignKey(settings.AUTH_USER_MODEL)
    file        = models.FileField(upload_to=upload_csv_file, validators=[csv_file_validator])
    completed   = models.BooleanField(default=False)

    def __str__(self):
        return self.user.username


def convert_header(csvHeader):
    header_ = csvHeader[0]
    cols = [x.replace(' ', '_').lower() for x in header_.split(",")]
    return cols


def csv_upload_post_save(sender, instance, created, *args, **kwargs):
    if not instance.completed:
        csv_file = instance.file
        decoded_file = csv_file.read().decode('utf-8')
        io_string = io.StringIO(decoded_file)
        reader = csv.reader(io_string, delimiter=';', quotechar='|')
        header_ = next(reader)
        header_cols = convert_header(header_)
        parsed_items = []

        '''
        if using a custom signal
        '''
        for line in reader:
            parsed_row_data = {}
            i = 0
            row_item = line[0].split(',')
            for item in row_item:
                key = header_cols[i]
                parsed_row_data[key] = item
                i+=1
            parsed_items.append(parsed_row_data)
        csv_uploaded.send(sender=instance, user=instance.user, csv_file_list=parsed_items)
        ''' 
        if using a model directly
        for line in reader:
            new_obj = YourModelKlass()
            i = 0
            row_item = line[0].split(',')
            for item in row_item:
                key = header_cols[i]
                setattr(new_obj, key) = item
                i+=1
            new_obj.save()
        '''
        instance.completed = True
        instance.save()


post_save.connect(csv_upload_post_save, sender=StaffCSVUpload)

Signals.py ( yourapp.signals.py)

import django.dispatch

csv_uploaded = django.dispatch.Signal(providing_args=["user", "csv_file_list"])

Field Validator (yourapp.validators.py):

import csv
import os
import io

from django.core.exceptions import ValidationError

REQUIRED_HEADER  = ['First Name','Last Name','Email','Username']

def csv_file_validator(value):
    filename, ext = os.path.splitext(value.name)
    if  str(ext) != '.csv':
         raise ValidationError("Must be a csv file")
    decoded_file = value.read().decode('utf-8')
    io_string = io.StringIO(decoded_file)
    reader = csv.reader(io_string, delimiter=';', quotechar='|')
    header_ = next(reader)[0].split(',')
    if header_[-1] == '':
        header_.pop()
    required_header = REQUIRED_HEADER
    if required_header != header_:
        raise ValidationError("Invalid File. Please use valid CSV Header and/or Staff Upload Template.")
    return True

Источник: https://www.codingforentrepreneurs.com/blog/csv-file-to-django-models/

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *