1

Looking at:

https://docs.djangoproject.com/en/3.1/ref/models/instances/#django.db.models.Model.save

For convenience, each model has an AutoField named id by default unless you explicitly specify primary_key=True on a field in your model. See the documentation for AutoField for more details.

and

https://docs.djangoproject.com/en/3.1/topics/db/models/

it seems clear that an object always has an id. I have a model:

class Currency(models.Model):
    currency_name = models.CharField(max_length=100)
    currency_value_in_dollars = models.FloatField()
    currency_value_in_dollars_date = models.DateField()

    def __str__(self):
        return self.currency_name

that I've migrated as:

operations = [
    migrations.CreateModel(
        name='Currency',
        fields=[
            ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
            ('currency_name', models.CharField(max_length=100)),
            ('currency_value_in_dollars', models.FloatField()),
            ('currency_value_in_dollars_date', models.DateField()),
        ],
    ),

and when trying to add entries to the db like:

def update_coins_table():
    if not do_greeting():
        print("Gecko crypto board not reachable. Db setup")
        return

    crypto_coins_prices = cg.get_price(ids=coins_ids_str, vs_currencies='usd')
    timezone_now = timezone.now()
    for coin_key in crypto_coins_prices:
        coin = Currency(coin_key, crypto_coins_prices[coin_key]['usd'], timezone_now)
        coin.save()

the line:

coin = Currency(coin_key, crypto_coins_prices[coin_key]['usd'], timezone_now)

gives:

unable to get repr for <class 'manage_crypto_currency.models.Transaction'> 

and

coin.save()

fails. If I replace the line in question with:

coin = Currency(1, coin_key, crypto_coins_prices[coin_key]['usd'], timezone_now)

it works. Shouldn't the id auto increment?

The last line always overwrites the previous and only one entry gets stored in the end.

Sebi
  • 4,262
  • 13
  • 60
  • 116

1 Answers1

1

The first positional parameter is still the id. Whether that is an AutoField or not is irrelevant. Especially since Django also uses the constructor to load model objects from the database, and sometimes you want to specify the id, because you want to update an object.

You can use None if you do not want to specify the primary key:

#                &downarrow; use None such that the database will provide an id
coin = Currency(None, coin_key, crypto_coins_prices[coin_key]['usd'], timezone_now)

but regardless, the is still "unstable", since adding an extra field somewhere results in the fact that the order of the parameters will change. It is better to use named parameters:

coin = Currency(
    currency_name=coin_key,
    currency_value_in_dollars=crypto_coins_prices[coin_key]['usd'],
    currency_value_in_dollars_date=timezone_now
)

Note: Django's DateTimeField [Django-doc] has a auto_now_add=… parameter [Django-doc] to work with timestamps. This will automatically assign the current datetime when creating the object, and mark it as non-editable (editable=False), such that it does not appear in ModelForms by default.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555