简体   繁体   中英

django.core.exceptions.ValidationError value must be a decimal number

So, I have two different django models, I want to fill one field in one model (that is configured as CharField) with some string, based on a condition, what string is in an other model. I wrote a simple method for that: method screenshot

    def detect_closing_reason(self):
        if self.recommendation.stoploss is None:
            return 'Non-recognized'
        else:
            return 'Closing by a stoploss'

In next method of a class I'm trying to call this method inside of a creating and saving a model instance: model creating and saving

    def create_virtual_transaction(self):
        date = self.recommendation.posted_time
        posix_date = datetime.timestamp(date)
        vo = VirtualTransaction.objects.create(start_price=self.recommendation.buy_levels,
                                               start_date=posix_date,
                                               end_price=self.recommendation.sell_levels,
                                               end_date=None,
                                               is_closed=None,
                                               author=self.take_author(),
                                               stock=self.recommendation.stock,
                                               coin=self.recommendation.coin,
                                               closing_reason=self.detect_closing_reason()))
        vo.save()

When I run this via django management command, I'm receiving this error: error screenshot

Traceback (most recent call last):
  File "/home/work/.local/share/virtualenvs/signals-3Fvtwo2f/lib/python3.7/site-packages/django/db/models/fields/__init__.py", line 1554, in to_python
    return decimal.Decimal(value)
decimal.InvalidOperation: [<class 'decimal.ConversionSyntax'>]

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "manage.py", line 21, in <module>
    main()
  File "manage.py", line 17, in main
    execute_from_command_line(sys.argv)
  File "/home/work/.local/share/virtualenvs/signals-3Fvtwo2f/lib/python3.7/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_line
    utility.execute()
  File "/home/work/.local/share/virtualenvs/signals-3Fvtwo2f/lib/python3.7/site-packages/django/core/management/__init__.py", line 375, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/work/.local/share/virtualenvs/signals-3Fvtwo2f/lib/python3.7/site-packages/django/core/management/base.py", line 323, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/home/work/.local/share/virtualenvs/signals-3Fvtwo2f/lib/python3.7/site-packages/django/core/management/base.py", line 364, in execute
    output = self.handle(*args, **options)
  File "/home/work/signals/trading_signals/parser/management/commands/add_virtual_transaction.py", line 21, in handle
    pc.create_virtual_transaction()
  File "/home/work/signals/trading_signals/parser/profit_analysis.py", line 57, in create_virtual_transaction
    closing_reason=self.detect_closing_reason())
  File "/home/work/.local/share/virtualenvs/signals-3Fvtwo2f/lib/python3.7/site-packages/django/db/models/manager.py", line 82, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/work/.local/share/virtualenvs/signals-3Fvtwo2f/lib/python3.7/site-packages/django/db/models/query.py", line 422, in create
    obj.save(force_insert=True, using=self.db)
  File "/home/work/.local/share/virtualenvs/signals-3Fvtwo2f/lib/python3.7/site-packages/django/db/models/base.py", line 741, in save
    force_update=force_update, update_fields=update_fields)
  File "/home/work/.local/share/virtualenvs/signals-3Fvtwo2f/lib/python3.7/site-packages/django/db/models/base.py", line 779, in save_base
    force_update, using, update_fields,
  File "/home/work/.local/share/virtualenvs/signals-3Fvtwo2f/lib/python3.7/site-packages/django/db/models/base.py", line 870, in _save_table
    result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
  File "/home/work/.local/share/virtualenvs/signals-3Fvtwo2f/lib/python3.7/site-packages/django/db/models/base.py", line 908, in _do_insert
    using=using, raw=raw)
  File "/home/work/.local/share/virtualenvs/signals-3Fvtwo2f/lib/python3.7/site-packages/django/db/models/manager.py", line 82, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/work/.local/share/virtualenvs/signals-3Fvtwo2f/lib/python3.7/site-packages/django/db/models/query.py", line 1186, in _insert
    return query.get_compiler(using=using).execute_sql(return_id)
  File "/home/work/.local/share/virtualenvs/signals-3Fvtwo2f/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 1334, in execute_sql
    for sql, params in self.as_sql():
  File "/home/work/.local/share/virtualenvs/signals-3Fvtwo2f/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 1278, in as_sql
    for obj in self.query.objs
  File "/home/work/.local/share/virtualenvs/signals-3Fvtwo2f/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 1278, in <listcomp>
    for obj in self.query.objs
  File "/home/work/.local/share/virtualenvs/signals-3Fvtwo2f/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 1277, in <listcomp>
    [self.prepare_value(field, self.pre_save_val(field, obj)) for field in fields]
  File "/home/work/.local/share/virtualenvs/signals-3Fvtwo2f/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 1218, in prepare_value
    value = field.get_db_prep_save(value, connection=self.connection)
  File "/home/work/.local/share/virtualenvs/signals-3Fvtwo2f/lib/python3.7/site-packages/django/db/models/fields/__init__.py", line 1563, in get_db_prep_save
    return connection.ops.adapt_decimalfield_value(self.to_python(value), self.max_digits, self.decimal_places)
  File "/home/work/.local/share/virtualenvs/signals-3Fvtwo2f/lib/python3.7/site-packages/django/db/models/fields/__init__.py", line 1559, in to_python
    params={'value': value},
django.core.exceptions.ValidationError: ["'[]' value must be a decimal number."]

Both fields (first I'm taking from another model in a method on a first screenshot, second I'm trying to save in a DB) configured as CharField: first field second field

class TelegramRecommendation(models.Model):
    channel_name = models.CharField(max_length=2000, blank=True, null=True)
    channel_forwarded_name = models.CharField(max_length=2000, blank=True, null=True)
    stock = models.CharField(max_length=2000, blank=True, null=True)
    coin = models.CharField(max_length=2000, blank=True, null=True)
    message = models.TextField(blank=True, null=True)
    buy_levels = models.CharField(max_length=2000, blank=True, null=True)
    sell_levels = models.CharField(max_length=2000, blank=True, null=True)
    posted_time = models.DateTimeField(default=None)
    stoploss = models.CharField(max_length=2000, blank=True, null=True)

    class Meta:
        ordering = ('channel_forwarded_name', 'posted_time')


class VirtualTransaction(models.Model):
    author = models.ForeignKey(Recommender, on_delete=models.CASCADE)
    stock = models.CharField(max_length=2000, blank=True, null=True)
    coin = models.CharField(max_length=2000, blank=True, null=True)
    start_date = models.CharField(max_length=2000, blank=True, null=True)
    end_date = models.CharField(max_length=2000, blank=True, null=True)
    start_price = models.DecimalField(max_digits=16, decimal_places=8, blank=True, null=True)
    end_price = models.DecimalField(max_digits=16, decimal_places=8, blank=True, null=True)
    is_closed = models.CharField(max_length=2000, blank=True, null=True)
    closing_reason = models.CharField(max_length=2000, blank=True, null=True)

I had tried to reset migrations and to drop and create a DB (PostgreSQL 11.4), that hadn't helped. my 0001_initial.py migration

migrations.CreateModel(
            name='TelegramRecommendation',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('channel_name', models.CharField(blank=True, max_length=2000)),
                ('channel_forwarded_name', models.CharField(blank=True, max_length=2000)),
                ('stock', models.CharField(blank=True, max_length=2000)),
                ('coin', models.CharField(blank=True, max_length=2000)),
                ('message', models.TextField(blank=True, null=True)),
                ('buy_levels', models.CharField(blank=True, max_length=2000)),
                ('sell_levels', models.CharField(blank=True, max_length=2000)),
                ('posted_time', models.DateTimeField(default=None)),
                ('stoploss', models.CharField(blank=True, max_length=2000)),
            ],
            options={
                'ordering': ('channel_forwarded_name', 'posted_time'),
            },
        ),
        migrations.CreateModel(
            name='VirtualTransaction',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('stock', models.CharField(blank=True, max_length=2000)),
                ('coin', models.CharField(blank=True, max_length=2000)),
                ('start_date', models.CharField(blank=True, max_length=2000)),
                ('end_date', models.CharField(blank=True, max_length=2000)),
                ('start_price', models.DecimalField(decimal_places=8, max_digits=16)),
                ('end_price', models.DecimalField(decimal_places=8, max_digits=16)),
                ('is_closed', models.CharField(blank=True, max_length=2000)),
                ('closing_reason', models.CharField(blank=True, max_length=2000)),
                ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='parser.Recommender')),

And my \\d+ tablename result from a psql table information

I had found some similar question here, but nothing had helped, I had tried: reset migrations, cast a string as a Decimal built-in instance

I don't have so much expirience in django and I could make a silly mistake, but I spent troubleshooting around 12 hours already, so I decided to write a question here.

The error is caused by some of the 2 DecimalField you have in the model VirtualTransaction ( start_price or end_price ). It only looks like the error is in self.detect_closing_reason() because that is the last parameter to .objects.create() ; the error actually happens because one of the DecimalField s

Most likely, the contents of one of the CharField s self.recommendation.buy_levels or self.recommendation.sell_levels cannot be converted to a Decimal instance.

Also, after using the method .objects.create() you don't need to call .save() on the returned object if you don't modify anything after the .objects.create() call.

To discover the error easier, I recommend to change your code to this:

def create_virtual_transaction(self):
    date = self.recommendation.posted_time
    posix_date = datetime.timestamp(date)

    vo = VirtualTransaction()
    vo.start_price = self.recommendation.buy_levels
    vo.start_date = posix_date
    vo.end_price = self.recommendation.sell_levels
    vo.end_date = None
    vo.is_closed = None
    vo.author = self.take_author()
    vo.stock = self.recommendation.stock
    vo.coin = self.recommendation.coin
    vo.closing_reason = self.detect_closing_reason()
    vo.full_clean()
    vo.save()

Note the call to vo.full_clean() ; this line will raise a much more specific error message, indicating the field that causes the error.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM