слишком длинное значение для изменяемого символа (25) - PullRequest
0 голосов
/ 11 декабря 2019

У меня проблемы с загрузкой файла CSV в мою базу данных, когда я пытаюсь загрузить файл, я получаю сообщение об ошибке «значение, слишком длинное для изменяемого символа (25)» для поля performance_exccy (см. Ниже мой djangoмодель). Это сообщение об ошибке начало появляться, когда я переключился с SQLite на PostgreSQL (используя ElephantSQL), с SQLite загрузка прошла отлично.

Значение, вызвавшее проблему, было 0,000000000000000000, которое имеет 20 символов, но в моей модели я определил max_digit = 40 и dec_places =20 - поэтому количество цифр не должно быть проблемой. Что я также заметил, так это то, что ошибка загрузки началась не с первой строки файла CSV, а с 12-й строки, строки которой имели значения одинаковой длины.

Моя модель:

class Testdata3(models.Model):
    key = models.CharField(max_length=100, primary_key=True)
    mnemonic = models.CharField(max_length=50)
    assetclass = models.CharField(max_length=25)
    value = models.DecimalField(max_digits=25,decimal_places=10)
    performance = models.DecimalField(max_digits=40,decimal_places=20)
    performance_exccy = models.DecimalField(max_digits=40,decimal_places=20)
    performance_abs = models.DecimalField(max_digits=40,decimal_places=20)
    performance_abs_exccy = models.DecimalField(max_digits=40,decimal_places=20)
    date = models.DateField()

    def __str__(self):
        return self.key

Мой взгляд:

def file_upload(request):
    template = "upload.html"
    prompt = {
        'order': 'Order of the CSV should be "placeholder_1", "placeholder_2", "placeholder_3" '
    }

    if request.method == "GET":
        return render(request, template, prompt)

    csv_file = request.FILES['file']

    if not csv_file.name.endswith('.csv'):
        messages.error(request, 'This is not a csv file')

    data_set = csv_file.read().decode('UTF-8')

    io_string = io.StringIO(data_set)

    #Ignores header row by jumping to next row
    next(io_string) 

    for column in csv.reader(io_string, delimiter=';', quotechar="|"):
        # Check if csv-row is empty, if true jump to next iteration/row
        if all(elem == "" for elem in column):
            next
        else:
            _, created = Testdata3.objects.update_or_create(
                key = column[0],

                defaults = {
                'key' : column[0],
                # Get everything after the date part in the primary key
                'mnemonic': re.findall(r'AMCS#[0-9]*(.*)', column[0])[0],
                # Create datetime object from a string
                'date' : datetime.datetime.strptime(column[6], '%d/%m/%Y'),
                'assetclass' : column[10],
                'value' : column[16], 
                'performance' : column[19],
                'performance_abs' : column[20],
                'performance_abs_exccy' : column[30],
                'performance_exccy' : column[31],
                }
            )
        context = {}

    return render(request, template, context)

1 Ответ

0 голосов
/ 11 декабря 2019

PostgreSQL рекомендует просто использовать текстовый тип для строк переменной ширины, если вы не хотите применять максимум. Использование текста не влияет на производительность.

https://github.com/npgsql/efcore.pg/issues/342

...