mathandpencil / django-bulk-sync

Combine bulk add, update, and delete into a single call.
MIT License
53 stars 15 forks source link

matching query does not exist. #14

Closed radarlwd closed 4 years ago

radarlwd commented 4 years ago

Hi Scott! Thank you for creating this package. I was using this package to update my database. The only issue was it didn't delete the object which was supposed to be deleted. After running my unit test, I got the following error message:

ERROR: test_all_features_at_once (orders.tests.TestBulkSync)

Traceback (most recent call last): File "/home/radar/GitHub/customer_platform/main_platform/orders/tests.py", line 76, in test_all_features_at_once ret = bulk_sync(new_models=new_objs, filters=Q(year_of_order=2020), key_fields=('sales_order_num', File "/home/radar/GitHub/customer_platform/env/customer_platform/lib/python3.7/site-packages/bulk_sync/init.py", line 63, in bulk_sync objs.filter(pk_in=[.pk for _ in list(obj_dict.values())]).delete() File "/home/radar/GitHub/customer_platform/env/customer_platform/lib/python3.7/site-packages/django/db/models/query.py", line 722, in delete deleted, _rows_count = collector.delete() File "/home/radar/GitHub/customer_platform/env/customer_platform/lib/python3.7/site-packages/django/db/models/deletion.py", line 338, in delete sender=model, instance=obj, using=self.using File "/home/radar/GitHub/customer_platform/env/customer_platform/lib/python3.7/site-packages/django/dispatch/dispatcher.py", line 175, in send for receiver in self._live_receivers(sender) File "/home/radar/GitHub/customer_platform/env/customer_platform/lib/python3.7/site-packages/django/dispatch/dispatcher.py", line 175, in for receiver in self._live_receivers(sender) File "/home/radar/GitHub/customer_platform/env/customer_platform/lib/python3.7/site-packages/simple_history/models.py", line 488, in post_delete self.create_historical_record(instance, "-", using=using) File "/home/radar/GitHub/customer_platform/env/customer_platform/lib/python3.7/site-packages/simple_history/models.py", line 499, in create_historical_record attrs[field.attname] = getattr(instance, field.attname) File "/home/radar/GitHub/customer_platform/env/customer_platform/lib/python3.7/site-packages/django/db/models/query_utils.py", line 139, in get instance.refresh_from_db(fields=[field_name]) File "/home/radar/GitHub/customer_platform/env/customer_platform/lib/python3.7/site-packages/django/db/models/base.py", line 627, in refresh_from_db db_instance = db_instance_qs.get() File "/home/radar/GitHub/customer_platform/env/customer_platform/lib/python3.7/site-packages/django/db/models/query.py", line 417, in get self.model._meta.object_name orders.models.Order.DoesNotExist: Order matching query does not exist.

This is the model I am using `from django.conf import settings from django.core.validators import MinValueValidator from django.db import models from django.urls import reverse from django.template.defaultfilters import date import time

from simple_history.models import HistoricalRecords

class Order(models.Model): user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name='username') shipment = models.ForeignKey('shipments.Shipment',on_delete=models.SET_NULL, related_name='orders', null=True, blank=True) #set null on delete

order_num = models.CharField(max_length=50, verbose_name='order #')
sales_order_num = models.CharField(max_length=50, verbose_name='SO #')
shipment_num = models.CharField(max_length=50, verbose_name='shipment #')
sku = models.CharField(max_length=50, blank=True, null=True, verbose_name='SKU')
description = models.CharField(max_length=300, verbose_name='Product')
num_planned = models.PositiveIntegerField(verbose_name='Plan to ship', default=0)
promise_date = models.DateField(verbose_name="Promise Date", null=True)
ship_date = models.DateField(blank=True, null=True, verbose_name='Ex Factory Ship Date')
status = models.CharField(max_length=25)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)

# Use this to sync orders
year_of_order = models.IntegerField(validators=[MinValueValidator(2000, message='Minimum value is 2000.')],
                                    verbose_name='Year of Order',
                                    help_text='This is the year of order')

history = HistoricalRecords()

class Meta:
    ordering = ('-created',)
    unique_together = (("sales_order_num", "shipment_num", "description"),)`

Here is my unit test `from bulk_sync import bulk_sync from django.contrib.auth.models import User from django.db.models import Q from django.test import TestCase

from .models import Order

class TestBulkSync(TestCase): """ Test bulk_sync method """

def setUp(self):
    self.user = User.objects.create_user(username='Customer1', email='abc@gmail.com', password='top_secret')
    # pass

def test_all_features_at_once(self):
    o1 = Order.objects.create(
        user=self.user,
        shipment=None,
        order_num='PO-0231',
        sales_order_num='AB199217',
        shipment_num='2020_Shipment A',
        sku=None,
        description='d1',
        num_planned=50,
        promise_date='2020-01-17',
        ship_date='2020-01-15',
        status='delivered',
        created='2020-07-28 22:11:39.120144+00:00',
        updated='2020-07-28 22:11:39.120161+00:00',
        year_of_order=2020,
        # history=None
    )

    o2 = Order.objects.create(
        user=self.user,
        shipment=None,
        order_num='PO-0231',
        sales_order_num='AB199217',
        shipment_num='2020_Shipment A',
        sku=None,
        description='d2',
        num_planned=700,
        promise_date='2020-01-17',
        ship_date='2020-01-15',
        status='delivered',
        created='2020-07-28 08:48:40.952583+00:00',
        updated='2020-07-28 08:48:40.952599+00:00',
        year_of_order=2020,
        # history=None
    )

    new_objs = [
    Order(
        user=self.user,
        shipment=None,
        order_num='PO-0231',
        sales_order_num='AB199217',
        shipment_num='2020_Shipment A',
        sku=None,
        description='d2',
        num_planned=700,
        promise_date='2020-01-17',
        ship_date='2020-01-15',
        status='delivered',
        created=None,
        updated=None,
        year_of_order=2020,
        # history=None
    )
    ]

    ret = bulk_sync(new_models=new_objs, filters=Q(year_of_order=2020), key_fields=('sales_order_num',
                                                                                    'description', 'shipment_num',))
    # try to delete o1
    with self.assertRaises(Order.DoesNotExist):
        Order.objects.get(id=o1.id)`
radarlwd commented 4 years ago

I finally fixed the bug by adding cascade_delete_history=True when creating the field history = HistoricalRecords(). Therefore it's related to how I handled the history.