Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

update_or_create for specific table rows

I got a model like this:

class AssignedTip(models.Model):
    """Model representing a tip (but not a specific copy of a tip)."""
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    date = models.DateField(null=True)
    note = models.CharField(max_length=50, default="Tip")
    amount = models.FloatField()
    minutes = models.FloatField(default=0)

    class Meta:
        unique_together = ('user', 'date',)

so there is a unique constraint with user+date.

Now I want to insert new data into the table. but if the unique constraint is matched, it should update the object instead of creating a new one. How can I do this. Using create_or_update gives me an error and is not updating the item. How can I tell it to update if constraing is matched?:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

AssignedTip.objects.update_or_create(user=User.objects.get(id=user), amount=user_amount, date=day.date(), minutes=minutes)

I get this error:

Environment:


Request Method: GET
Request URL: http://0.0.0.0:8000/tasks/

Django Version: 4.0.8
Python Version: 3.10.12
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'widget_tweaks',
 'tasks.apps.TasksConfig',
 'tips.apps.TipsConfig',
 'ratings.apps.RatingsConfig',
 'procedures.apps.ProceduresConfig',
 'inventory.apps.InventoryConfig',
 'registration.apps.RegistrationConfig',
 'ckeditor',
 'crispy_forms',
 'crispy_bootstrap4',
 'django_crontab']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'whitenoise.middleware.WhiteNoiseMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'login_required.middleware.LoginRequiredMiddleware']



Traceback (most recent call last):
  File "/home/raphael/.conda/envs/iaro/lib/python3.10/site-packages/django/db/models/query.py", line 657, in get_or_create
    return self.get(**kwargs), False
  File "/home/raphael/.conda/envs/iaro/lib/python3.10/site-packages/django/db/models/query.py", line 496, in get
    raise self.model.DoesNotExist(

During handling of the above exception (AssignedTip matching query does not exist.), another exception occurred:
  File "/home/raphael/.conda/envs/iaro/lib/python3.10/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
  File "/home/raphael/.conda/envs/iaro/lib/python3.10/site-packages/django/db/backends/sqlite3/base.py", line 477, in execute
    return Database.Cursor.execute(self, query, params)

The above exception (UNIQUE constraint failed: tips_assignedtip.user_id, tips_assignedtip.date) was the direct cause of the following exception:
  File "/home/raphael/.conda/envs/iaro/lib/python3.10/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/home/raphael/.conda/envs/iaro/lib/python3.10/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/raphael/development/iaro/iaroapp/tasks/views.py", line 86, in index
    assignTips(datetime.today().replace(day=7))
  File "/home/raphael/development/iaro/iaroapp/iaroapp/cron.py", line 71, in assignTips
    AssignedTip.objects.update_or_create(user=User.objects.get(id=user), amount=user_amount, date=day.date(), minutes=minutes)
  File "/home/raphael/.conda/envs/iaro/lib/python3.10/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/raphael/.conda/envs/iaro/lib/python3.10/site-packages/django/db/models/query.py", line 684, in update_or_create
    obj, created = self.select_for_update().get_or_create(defaults, **kwargs)
  File "/home/raphael/.conda/envs/iaro/lib/python3.10/site-packages/django/db/models/query.py", line 664, in get_or_create
    return self.create(**params), True
  File "/home/raphael/.conda/envs/iaro/lib/python3.10/site-packages/django/db/models/query.py", line 514, in create
    obj.save(force_insert=True, using=self.db)
  File "/home/raphael/.conda/envs/iaro/lib/python3.10/site-packages/django/db/models/base.py", line 806, in save
    self.save_base(
  File "/home/raphael/.conda/envs/iaro/lib/python3.10/site-packages/django/db/models/base.py", line 857, in save_base
    updated = self._save_table(
  File "/home/raphael/.conda/envs/iaro/lib/python3.10/site-packages/django/db/models/base.py", line 1000, in _save_table
    results = self._do_insert(
  File "/home/raphael/.conda/envs/iaro/lib/python3.10/site-packages/django/db/models/base.py", line 1041, in _do_insert
    return manager._insert(
  File "/home/raphael/.conda/envs/iaro/lib/python3.10/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/raphael/.conda/envs/iaro/lib/python3.10/site-packages/django/db/models/query.py", line 1434, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
  File "/home/raphael/.conda/envs/iaro/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 1621, in execute_sql
    cursor.execute(sql, params)
  File "/home/raphael/.conda/envs/iaro/lib/python3.10/site-packages/django/db/backends/utils.py", line 103, in execute
    return super().execute(sql, params)
  File "/home/raphael/.conda/envs/iaro/lib/python3.10/site-packages/django/db/backends/utils.py", line 67, in execute
    return self._execute_with_wrappers(
  File "/home/raphael/.conda/envs/iaro/lib/python3.10/site-packages/django/db/backends/utils.py", line 80, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/home/raphael/.conda/envs/iaro/lib/python3.10/site-packages/django/db/backends/utils.py", line 84, in _execute
    with self.db.wrap_database_errors:
  File "/home/raphael/.conda/envs/iaro/lib/python3.10/site-packages/django/db/utils.py", line 91, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/home/raphael/.conda/envs/iaro/lib/python3.10/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
  File "/home/raphael/.conda/envs/iaro/lib/python3.10/site-packages/django/db/backends/sqlite3/base.py", line 477, in execute
    return Database.Cursor.execute(self, query, params)

Exception Type: IntegrityError at /tasks/
Exception Value: UNIQUE constraint failed: tips_assignedtip.user_id, tips_assignedtip.date

>Solution :

Add these to the defaults=… parameter [Django-doc]:

AssignedTip.objects.update_or_create(
    user_id=user,
    date=day.date(),
    defaults=dict(amount=user_amount, minutes=minutes),
)

or equivalent:

AssignedTip.objects.update_or_create(
    user_id=user,
    date=day.date(),
    defaults={'amount': user_amount, 'minutes': minutes},
)

It thus will check if the user_id and date matches, and if so, update with the defaults=… and if not create an item with that user_id and date and the defaults=….

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading