Commits

Viorel Stirbu  committed abb4bc9

synchronize basic product to local database

  • Participants
  • Parent commits c8afffd

Comments (0)

Files changed (3)

File atexpc/atex_web/management/commands/sync_products.py

+from django.core.management.base import NoArgsCommand
+from atexpc.atex_web.models import Product, Categories
+
+import logging
+logger = logging.getLogger(__name__)
+
+# http://www.preetk.com/node/optimizing-mass-commits-django-django_bulk_save/
+# http://people.iola.dk/olau/python/bulkops.py
+
+class Command(NoArgsCommand):
+    excluded_fields = ['updated', 'has_folder']
+    update_fields = [f.name for f in Product._meta.fields if f.name not in excluded_fields]
+
+    def _model_product_dict(self, product, category_id):
+        model_dict = {}
+        for field in self.update_fields:
+            if field == 'id':
+                model_dict[field] = int(product.get(field))
+            else:
+                model_dict[field] = product.get(field)
+        model_dict['category_id'] = int(category_id)
+        return model_dict
+
+    def _updated_product(self, product, product_update_dict):
+        """ Returns updated product if the dict contains new data,
+            otherwise returns None"""
+        updated = False
+        for field, new_value in product_update_dict.items():
+            if new_value != getattr(product, field):
+                setattr(product, field, new_value)
+                updated = True
+        return product if updated else None
+
+    def _create_or_update_products(self, products):
+        existing_products = Product.objects.in_bulk(products.keys())
+        for product_id, new_product in products.items():
+            old_product = existing_products.get(product_id)
+            if old_product:
+                updated_product = self._updated_product(old_product, new_product)
+                if updated_product:
+                    logger.debug("Update %s", updated_product)
+                    updated_product.save()
+
+        insert_ids = products.viewkeys() - existing_products.viewkeys()
+        insert_list = [Product(**products[i]) for i in insert_ids]
+        logger.debug("Insert %s", insert_list)
+        Product.objects.bulk_create(insert_list)
+
+        delete_ids = existing_products.viewkeys() - products.viewkeys()
+        delete_list = [existing_products.get(i) for i in delete_ids]
+        logger.debug("Delete %s", delete_list)
+        for old_product in delete_list:
+            old_product.delete()
+
+    def handle_noargs(self, *args, **options):
+        categories = Categories().get_all()
+        # TODO: delete old categories
+        for category in categories:
+            category_id = category['id']
+            logger.debug("Category %(name)s (%(count)d)", category)
+            if category['count'] > 0:
+                products = Product.objects.get_products(
+                    category_id=category_id, keywords=None,
+                    start=None, stop=None).get('products')
+                products_dict = dict((int(p['id']), self._model_product_dict(p, category_id))
+                                     for p in products)
+                self._create_or_update_products(products_dict)
+
+        # Assign existing images for new products
+        Product.objects.assign_images()

File atexpc/atex_web/migrations/0011_add_product_fields_name_category_id_updated.py

+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+from django.utils.timezone import now
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding field 'Product.name'
+        db.add_column('atex_web_product', 'name',
+                      self.gf('django.db.models.fields.CharField')(default='', max_length=255),
+                      keep_default=False)
+
+        # Adding field 'Product.category_id'
+        db.add_column('atex_web_product', 'category_id',
+                      self.gf('django.db.models.fields.IntegerField')(null=True),
+                      keep_default=False)
+
+        # Adding field 'Product.updated'
+        db.add_column('atex_web_product', 'updated',
+                      self.gf('django.db.models.fields.DateTimeField')(auto_now=True, auto_now_add=True, default=now(), blank=True),
+                      keep_default=False)
+
+
+    def backwards(self, orm):
+        # Deleting field 'Product.name'
+        db.delete_column('atex_web_product', 'name')
+
+        # Deleting field 'Product.category_id'
+        db.delete_column('atex_web_product', 'category_id')
+
+        # Deleting field 'Product.updated'
+        db.delete_column('atex_web_product', 'updated')
+
+
+    models = {
+        'atex_web.dropbox': {
+            'Meta': {'object_name': 'Dropbox'},
+            'app_key': ('django.db.models.fields.CharField', [], {'max_length': '64', 'primary_key': 'True'}),
+            'delta_cursor': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
+        },
+        'atex_web.hit': {
+            'Meta': {'object_name': 'Hit'},
+            'count': ('django.db.models.fields.IntegerField', [], {}),
+            'date': ('django.db.models.fields.DateField', [], {}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'product': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['atex_web.Product']"})
+        },
+        'atex_web.image': {
+            'Meta': {'object_name': 'Image'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'image': ('sorl.thumbnail.fields.ImageField', [], {'max_length': '255'}),
+            'path': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'}),
+            'product': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['atex_web.Product']", 'null': 'True', 'on_delete': 'models.SET_NULL'})
+        },
+        'atex_web.product': {
+            'Meta': {'object_name': 'Product'},
+            'category_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'auto_now_add': 'True', 'blank': 'True'})
+        }
+    }
+
+    complete_apps = ['atex_web']

File atexpc/atex_web/models.py

         map_getter = lambda folder_name: folder_product_map.get(folder_name)
         Image.objects.all().assign_all_unasigned(get_product_id_for_folder=map_getter)
 
-    def get_products(self, category_id, keywords, selectors,
-                     price_min, price_max, stock,
+    def get_products(self, category_id, keywords, selectors=None,
+                     price_min=None, price_max=None, stock=None,
                      start=None, stop=None, sort_by=None, sort_order=None):
         return self._ancora.search_products(
             category_id=category_id, keywords=keywords, selectors=selectors,
 
 class Product(models.Model):
     model = models.CharField(max_length=64, unique=True)
-    # name = models.CharField(max_length=255)
+    name = models.CharField(max_length=255)
+    category_id = models.IntegerField(null=True)
+    updated = models.DateTimeField(auto_now=True, auto_now_add=True)
     # has_folder = models.NullBooleanField()
 
     objects = ProductManager()