django update_or_create gets “duplicate key value violates unique constraint ”

前端 未结 3 2169
天涯浪人
天涯浪人 2021-02-19 21:03

Maybe I misunderstand the purpose of Django\'s update_or_create Model method.

Here is my Model:

from django.db import models
import datetime
from vc.mode         


        
相关标签:
3条回答
  • 2021-02-19 21:28

    This is already answered well in the above.

    To be more clear the update_or_create() method should have **kwargs as those parameters on which you want to check if that data already exists in DB by filtering.

    select some_column from table_name where column1='' and column2='';

    Filtering by **kwargs will give you objects. Now if you wish to update any data/column of those filtered objects, you should pass them in defaults param in update_or_create() method.

    so lets say you found an object based on a filter now the default param values are expected to be picked and updated.

    and if there's no matching object found based on the filter then it goes ahead and creates an entry with filters and the default param passed.

    0 讨论(0)
  • 2021-02-19 21:37

    You should separete your field:

    1. Fields that should be searching for
    2. Fields that should be updated

    for example: If I have the model:

    class User(models.Model):
        username = models.CharField(max_lenght=200)
        nickname = models.CharField(max_lenght=200)
    

    And I want to search for username = 'Nikolas' and update this instance nickname to 'Nik'(if no User with username 'Nikolas' I need to create it) I should write this code:

    User.objects.update_or_create(
        username='Nik', 
        defaults={'nickname': 'Nikolas'},
    )
    

    see in https://docs.djangoproject.com/en/2.0/ref/models/querysets/

    0 讨论(0)
  • 2021-02-19 21:47

    The update_or_create(defaults=None, **kwargs) has basically two parts:

    1. the **kwargs which specify the "filter" criteria to determine if such object is already present; and
    2. the defaults which is a dictionary that contains the fields mapped to values that should be used when we create a new row (in case the filtering fails to find a row), or which values should be updated (in case we find such row).

    The problem here is that you make your filters too restrictive: you add several filters, and as a result the database does not find such row. So what happens? The database then aims to create the row with these filter values (and since defaults is missing, no extra values are added). But then it turns out that we create a row, and that the combination of the cluster and added already exists. Hence the database refuses to add this row.

    So this line:

    Model.objects.update_or_create(field1=val1,
                                   field2=val2,
                                   defaults={
                                       'field3': val3,
                                       'field4': val4
                                   })
    

    Is to semantically approximately equal to:

    try:
        item = Model.objects.get(field1=val1, field2=val2)
    except Model.DoesNotExist:
        Model.objects.create(field1=val1, field2=val2, field3=val3, field4=val4)
    else:
        item = Model.objects.filter(
            field1=val1,
            field2=val2,
        ).update(
            field3 = val3
            field4 = val4
        )
    

    (but the original call is typically done in a single query).

    You probably thus should write:

    Vmt.objects.update_or_create(
        cluster=c,
        creation_time='test creaetion time',
        defaults = {        
            'current_pm_active': 6,
            'current_pm_total': 5,
        }
    )
    

    (or something similar)

    0 讨论(0)
提交回复
热议问题