Автоматическое поле должно присутствовать, но его нет (django)?

#python #python-3.x #django

#python #python-3.x #django

Вопрос:

Глядя на:

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

Для удобства каждая модель по умолчанию имеет автоматическое поле с именем id, если вы явно не укажете primary_key=True в поле вашей модели. Более подробную информацию см. В документации для автозаполнения.

и

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

кажется очевидным, что у объекта всегда есть идентификатор. У меня есть модель:

 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
 

что я перенес как:

 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()),
        ],
    ),
 

и при попытке добавить записи в БД, например:

 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()
 

строка:

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

дает:

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

и

 coin.save()
 

сбой. Если я заменю рассматриваемую строку на:

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

это работает. Разве идентификатор не должен автоматически увеличиваться?

Последняя строка всегда перезаписывает предыдущую, и в конце сохраняется только одна запись.

Ответ №1:

Первым позиционным параметром по-прежнему является id . Является ли это AutoField или нет, не имеет значения. Тем более, что Django также использует конструктор для загрузки объектов модели из базы данных, и иногда вы хотите указать идентификатор, потому что вы хотите обновить объект.

Вы можете использовать None , если не хотите указывать первичный ключ:

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

но, несмотря на это, оно по-прежнему «нестабильно», поскольку добавление дополнительного поля где-либо приводит к тому, что порядок параметров изменится. Лучше использовать именованные параметры:

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

Примечание: у Django DateTimeField [Django-doc]
есть auto_now_add=… параметр [Django-doc]
для работы с временными метками. Это автоматически назначит текущую дату
и время при создании объекта и пометит его как не редактируемый ( editable=False ), так
что он не отображается в ModelForm s по умолчанию.

Комментарии:

1. Удалось сохранить записи; можно было бы сделать немного более интуитивно понятным