Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Django 重复的键值违反唯一约束itemstaticlabel\u item\u id\u f9405967\u uniq_Django_Django Models_Django Database - Fatal编程技术网

Django 重复的键值违反唯一约束itemstaticlabel\u item\u id\u f9405967\u uniq

Django 重复的键值违反唯一约束itemstaticlabel\u item\u id\u f9405967\u uniq,django,django-models,django-database,Django,Django Models,Django Database,我知道,出现这个问题是因为代码试图使用已经存在的唯一键组合向数据库添加条目。但我的问题是:为什么以及如何预防这种情况?考虑到我的逻辑,这对我来说毫无意义 我有一段代码,基本上为发票存储一些静态标签。这样做的目的是在不存在标签的情况下动态创建标签,而不是在代码中的许多地方手动插入标签 每当生成项时,也会创建一个ItemInv,通过保存后者,我会检查是否存在静态标签。如果没有,则创建一个新的。显示发票/汇票时,也会调用获取(或创建)静态标签的代码 错误似乎就发生在那里。标签不存在,创建了一个新的标签

我知道,出现这个问题是因为代码试图使用已经存在的唯一键组合向数据库添加条目。但我的问题是:为什么以及如何预防这种情况?考虑到我的逻辑,这对我来说毫无意义

我有一段代码,基本上为发票存储一些静态标签。这样做的目的是在不存在标签的情况下动态创建标签,而不是在代码中的许多地方手动插入标签

每当生成
时,也会创建一个
ItemInv
,通过保存后者,我会检查是否存在静态标签。如果没有,则创建一个新的。显示发票/汇票时,也会调用获取(或创建)静态标签的代码

错误似乎就发生在那里。标签不存在,创建了一个新的标签,但不知何故,这种情况会发生两次?我的意思是,我真的不明白为什么代码会尝试两次添加相同的项。这可能是一个线程问题吗

我没有使用
get\u或\u create
,因为
ItemStaticInv
上的某些属性(
static\u account\u label
static\u agreement\u label
…)可以更新且不是唯一的。在创建发票之前,草稿具有相同的结构,并且可以更改数据,包括这些标签

class ItemInv(managers.Model):
    """
    Relation between Item and Invoice
    """
    item = models.ForeignKey('Item')
    invoice = models.ForeignKey('Invoice')
    [...]

    class Meta:
        unique_together = ('item', 'invoice')

    def save(self, *args, **kwargs):
        iteminv = super(ItemInv, self).save(*args, **kwargs)

        # If the item does not have the static information, one should be created
        self.item.get_invoice_static(self.invoice)

        return iteminv


class Item(managers.Model):
    """
     Item to be put on an invoice
    """

    serial = models.AutoField(primary_key=True)  # Software license
    product = models.ForeignKey('Product', verbose_name='Product')
    account = models.ForeignKey('Account', verbose_name='Account', related_name='items')
    [...]

    def get_invoice_static(self, document):
        try:
            return self.document_labels.get(invoice=document)
        except ObjectDoesNotExist:
            return ItemStaticLabel.objects.create(
                item=self,
                invoice=document,
                static_account_label=str(self.account),
                static_customer_label=str(self.account.customer),
                static_agreement_label=str(self.account.agreement)
            )


class ItemStaticLabel(managers.Model):
    """
    We must store static information about the Item on an invoice.
    """

    item = models.ForeignKey('Item', related_name='document_labels')
    invoice = models.ForeignKey('Invoice', related_name='item_labels')

    static_account_label = models.CharField(max_length=256, null=True, blank=True)
    static_customer_label = models.CharField(max_length=256, null=True, blank=True)
    static_agreement_label = models.CharField(max_length=256, null=True, blank=True)
    static_expiration_label = models.DateField(max_length=256, null=True, blank=True)

    class Meta:
        unique_together = ('item', 'invoice')
这有几个缺陷,但这个系统是由其他人开发的,正在生产中。我能做的结构性改变数量非常有限。因此,我必须试着理解是什么导致了这个问题

Traceback:

File "/home/apps/sites/invoice/source/v3/models.py" in get_invoice_static
  1105.             return self.document_labels.get(invoice=document)

File "/home/apps/sites/invoice/env/lib/python3.4/site-packages/django/db/models/manager.py" in manager_method
  85.                 return getattr(self.get_queryset(), name)(*args, **kwargs)

File "/home/apps/sites/invoice/env/lib/python3.4/site-packages/django/db/models/query.py" in get
  380.                 self.model._meta.object_name


      During handling of the above exception (ItemStaticLabel matching query does not exist.), another exception occurred:



File "/home/apps/sites/invoice/env/lib/python3.4/site-packages/django/db/backends/utils.py" in execute
  65.                 return self.cursor.execute(sql, params)


      The above exception (duplicate key value violates unique constraint "v3_itemstaticlabel_item_id_f9405967_uniq"
DETAIL:  Key (item_id, invoice_id)=(1840, 1578) already exists.
) was the direct cause of the following exception:



File "/home/apps/sites/invoice/env/lib/python3.4/site-packages/django/core/handlers/exception.py" in inner
  41.             response = get_response(request)

File "/home/apps/sites/invoice/env/lib/python3.4/site-packages/django/core/handlers/base.py" in _legacy_get_response
  249.             response = self._get_response(request)

File "/home/apps/sites/invoice/env/lib/python3.4/site-packages/django/core/handlers/base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)

File "/home/apps/sites/invoice/env/lib/python3.4/site-packages/django/core/handlers/base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/usr/local/lib/python3.4/contextlib.py" in inner
  30.                 return func(*args, **kwds)

File "/home/apps/sites/invoice/env/lib/python3.4/site-packages/django/views/generic/base.py" in view
  68.             return self.dispatch(request, *args, **kwargs)

File "/home/apps/sites/invoice/env/lib/python3.4/site-packages/django/views/generic/base.py" in dispatch
  88.         return handler(request, *args, **kwargs)

File "/home/apps/sites/invoice/env/lib/python3.4/site-packages/django/views/generic/detail.py" in get
  116.         context = self.get_context_data(object=self.object)

File "/home/apps/sites/invoice/source/web/views/invoice.py" in get_context_data
  280.         context['document_html'] = services.document_to_html(obj)

File "/home/apps/sites/invoice/source/v3/services.py" in document_to_html
  1550.             'account': set_[0].get_invoice_static(document).static_account_label,

File "/home/apps/sites/invoice/source/v3/models.py" in get_invoice_static
  1112.                 static_agreement_label=str(self.account.agreement)

File "/home/apps/sites/invoice/env/lib/python3.4/site-packages/django/db/models/manager.py" in manager_method
  85.                 return getattr(self.get_queryset(), name)(*args, **kwargs)

File "/home/apps/sites/invoice/env/lib/python3.4/site-packages/django/db/models/query.py" in create
  394.         obj.save(force_insert=True, using=self.db)

File "/home/apps/sites/invoice/source/v3/managers.py" in save
  724.         super().save(*args, **kwargs)

File "/home/apps/sites/invoice/env/lib/python3.4/site-packages/django/db/models/base.py" in save
  808.                        force_update=force_update, update_fields=update_fields)

File "/home/apps/sites/invoice/env/lib/python3.4/site-packages/django/db/models/base.py" in save_base
  838.             updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)

File "/home/apps/sites/invoice/env/lib/python3.4/site-packages/django/db/models/base.py" in _save_table
  924.             result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)

File "/home/apps/sites/invoice/env/lib/python3.4/site-packages/django/db/models/base.py" in _do_insert
  963.                                using=using, raw=raw)

File "/home/apps/sites/invoice/env/lib/python3.4/site-packages/django/db/models/manager.py" in manager_method
  85.                 return getattr(self.get_queryset(), name)(*args, **kwargs)

File "/home/apps/sites/invoice/env/lib/python3.4/site-packages/django/db/models/query.py" in _insert
  1076.         return query.get_compiler(using=using).execute_sql(return_id)

File "/home/apps/sites/invoice/env/lib/python3.4/site-packages/django/db/models/sql/compiler.py" in execute_sql
  1107.                 cursor.execute(sql, params)

File "/home/apps/sites/invoice/env/lib/python3.4/site-packages/django/db/backends/utils.py" in execute
  65.                 return self.cursor.execute(sql, params)

File "/home/apps/sites/invoice/env/lib/python3.4/site-packages/django/db/utils.py" in __exit__
  94.                 six.reraise(dj_exc_type, dj_exc_value, traceback)

File "/home/apps/sites/invoice/env/lib/python3.4/site-packages/django/utils/six.py" in reraise
  685.             raise value.with_traceback(tb)

File "/home/apps/sites/invoice/env/lib/python3.4/site-packages/django/db/backends/utils.py" in execute
  65.                 return self.cursor.execute(sql, params)

Exception Type: IntegrityError at /invoice-menu/customer/251/invoices/1578/
Exception Value: duplicate key value violates unique constraint "v3_itemstaticlabel_item_id_f9405967_uniq"
DETAIL:  Key (item_id, invoice_id)=(1840, 1578) already exists.
看法 服务
请显示发生错误的视图。@Alasdair我已经完成了。我担心它会变得太复杂而无法理解。这个项目中有很多依赖项(还有很多遗留问题)。您是否已经知道这是一种竞争条件(不同的请求试图同时创建同一个对象)还是在您单独执行一个请求时发生的?代码在获得完整性错误时会执行额外的查找,以尝试获取新创建的对象。请注意,
get\u或\u create
允许您指定默认值,因此您可能可以使用它。另外,我将避免调用
set\u0]。get\u invoice\u static(document)
summary.append()中一行三次,但我认为这不是问题所在。我不知道
get\u或\u create
的默认选项。我会调查的。它只发生在一个用户身上。您所说的调用
get\u invoice\u static
是有道理的,这可能就是问题所在。但是,这些都是不必要的调用。请显示发生错误的视图。@Alasdair我已经完成了。我担心它会变得太复杂而无法理解。这个项目中有很多依赖项(还有很多遗留问题)。您是否已经知道这是一种竞争条件(不同的请求试图同时创建同一个对象)还是在您单独执行一个请求时发生的?代码在获得完整性错误时会执行额外的查找,以尝试获取新创建的对象。请注意,
get\u或\u create
允许您指定默认值,因此您可能可以使用它。另外,我将避免调用
set\u0]。get\u invoice\u static(document)
summary.append()中一行三次,但我认为这不是问题所在。我不知道
get\u或\u create
的默认选项。我会调查的。它只发生在一个用户身上。您所说的调用
get\u invoice\u static
是有道理的,这可能就是问题所在。但是,这些都是不必要的电话。
class InvoiceDetailView(DetailView):
    model = Invoice
    template_name = 'invoice_detail.html'
    pk_url_kwarg = 'invoice_key'
    context_object_name = 'invoice'

    def get_context_data(self, **kwargs):
        context = super(InvoiceDetailView, self).get_context_data(**kwargs)

    obj = context[self.context_object_name]

    obj = models.Invoice.objects.filter(pk=obj.pk).select_related(
            'customer',
            'customer__original',
            'currency',
    ).prefetch_related(
            'citems',
            'citems__assocs',
            'citems__assocs__product',
            'iteminv_set',
            'iteminv_set__item',
    ).first()

    context['document_html'] = services.document_to_html(obj)

    return context
def document_to_html(document):
    """
    Renders the invoice to html.
    """
    from v3.models import Item, Maintenance, Invoice, CustomInvoiceLine
    from web.collection_utils import collapse_list
    data = {}

    items = Item.objects.on_invoice(document)
    mains = Maintenance.objects.on_invoice(document)

    rows = get_invoice_product_rows(document)
    # merge the lists
    rows['itemrows'].extend(rows['mainrows'])
    include_summary = len(rows['itemrows']) > 0 and not Invoice.objects.filter(creditted_by=document)

    # calc VAT lines
    vats = {}
    for ir in rows['itemrows']:
        row = ir['line']
        vat = ir['objs'][0].vat
        rate = ir['objs'][0].vat_rate
        total = (Decimal(rate / 100) * ir['rowtotal']).quantize(Decimal('.01'), rounding=ROUND_HALF_UP)
        try:
            vats[vat]['rownums'].append(row)
            vats[vat]['total'] += total
        except:
            vats[vat] = dict(rownums=[row, ], message=ir['objs'][0].vat_message, total=total, rate=rate)

    for mr in rows['mainrows']:
        row = mr['line']
        vat = mr['objs'][0].vat
        rate = mr['objs'][0].vat_rate
        total = (Decimal(rate / 100) * mr['rowtotal']).quantize(Decimal('.01'), rounding=ROUND_HALF_UP)
        try:
            vats[vat]['rownums'].append(row)
            # Changed it to not add any  value  because that will produce wrong vat output.
            vats[vat]['total'] += 0
        except:
            vats[vat] = dict(rownums=[row, ], message=mr['objs'][0].vat_message, total=total, rate=rate)

    for cr in rows['citemrows']:
        row = cr['line']
        vat = cr['obj'].vat
        rate = cr['obj'].vat_rate
        total = (Decimal(rate / 100) * cr['rowtotal']).quantize(Decimal('.01'), rounding=ROUND_HALF_UP)
        try:
            vats[vat]['rownums'].append(row)
            vats[vat]['total'] += total
        except:
            vats[vat] = [row, ]
            vats[vat] = dict(rownums=[row, ], message=cr['obj'].vat_message, total=total, rate=rate)

    vats = [(k, collapse_list(v['rownums']), v['message'], v['total'], v['rate']) for (k, v) in vats.items()]
    vats = sorted(vats, key=lambda x: x[1])

    # Gather data for the license agreement overview
    # A list of lists, where the inner lists contain items that match on product and account
    matched_item_sets = []

    items = list(items) + list([m.serial for m in mains])
    for item in items:
        # Find a set to add this item to
        for set_ in matched_item_sets:
            if item.product == set_[0].product and item.account == set_[0].account:
                if item not in set_:
                    set_.append(item)
                break
        else:
            # No matching set found. Create a new one
            matched_item_sets.append([item])

    # Package the item sets nicely with meta information
    summary = []
    for set_ in matched_item_sets:
        summary.append({
            'account': set_[0].get_invoice_static(document).static_account_label,
            'owner': set_[0].get_invoice_static(document).static_customer_label,
            'agreement': set_[0].get_invoice_static(document).static_agreement_label,
            'product': set_[0].product,
            'licenses': collapse_list(set_),
        })

    data['inv'] = document
    data['lines'] = rows['itemrows']
    data['citems'] = rows['citemrows']
    data['vats'] = vats
    data['lagree'] = summary
    data['includeSummary'] = include_summary
    data['cilines'] = CustomInvoiceLine.objects.filter(invoice=document, on_invoice=True)

    data['base_url'] = settings.SITE_BASE_URL
    tpl = document.template
    tpl = DjangoTemplate(tpl.content)
    return tpl.render(Context(data))