Giter Site home page Giter Site logo

Comments (6)

gregmuellegger avatar gregmuellegger commented on August 15, 2024

Hi, this issue got reported multiple times already but I cannot reproduce it. Maybe you can help me find the root cause of this? So:

  1. Can you tell me which Django version you are using
  2. Can you tell me more about the model that holds the m2m field that is causing the trouble?

from django-autofixture.

compfaculty avatar compfaculty commented on August 15, 2024

Django==1.5.4 (I do not remember exactly, but it seems the problem was with version 1.5.1 too)

class Product(CacheInvalidatorMixin, models.Model):
    """A product is sold within a shop.

    Parameters:
        - name
            The name of the product

        - slug
            Part of the URL

        - sku
            The external unique id of the product

        - price
            The gross price of the product

        - effective_price:
            Only for internal usage (price filtering).

        - unit
            The unit of the product. This is displayed beside the quantity
            field.

        - price_unit
            The unit of the product's price. This is displayed beside the price

        - short_description
            The short description of the product. This is used within overviews.

        - description
            The description of the product. This is used within the detailed view
            of the product.

        - images
            The images of the product.

        - meta_title
            the meta title of the product (the title of the HTML page).

        - meta_keywords
            the meta keywords of the product.

        - meta_description
            the meta description of the product.

        - related_products
            Related products for this products.

        - accessories
            Accessories for this products.

        - active
            If False the product won't be displayed to shop users.

        - creation_date
            The creation date of the product

        - deliverable
            If True the product is deliverable. Otherwise not.

        - manual_delivery_time
            If True the delivery_time of the product is taken. Otherwise the
            delivery time will be calculate on global delivery times and
            selected shipping method.

        - delivery_time
            The delivery time of the product. This is only relevant if
            manual_delivery_time is set to true.

        - order_time
            Order time of the product when no product is within the stock. This
            is added to the product's delivery time.

        - ordered_at
            The date when the product has been ordered. To calculate the rest of
            the order time since the product has been ordered.

        - manage_stock_amount
            If true the stock amount of the product will be decreased when a
            product has been saled.

        - weight, height, length, width
            The dimensions of the product relevant for the the stock (IOW the
            dimension of the product's box not the product itself).

        - tax
            Tax rate of the product.

        - variant_group_id
            This field is an integer number used to group products in variant group.
            All products that has same variant_group_id are considered to be varaints of each other

        - template
            Sets the template, which renders the product content. If left to None, default template is used.
    """
    # All products
    name = models.CharField(_(u"Name"), max_length=128, blank=True)
    slug = models.SlugField(_(u"Slug"), unique=True, max_length=80, db_index=True)
    sku = models.CharField(_(u"SKU"), blank=True, max_length=64, db_index=True)
    price = models.FloatField(_(u"Price"), default=0.0, db_index=True)
    cost_price = models.FloatField(_(u"Cost price"), default=0.0)
    wholesale_price = models.FloatField(_(u"Wholesale price"), default=0.0)
    supplier_price = models.FloatField(_(u"Supplier price"), default=0.0)
    effective_price = models.FloatField(_(u"Price"), blank=True)            # TODO : store it in session or cache
    price_unit = models.CharField(blank=True, max_length=20)
    unit = models.CharField(blank=True, max_length=20)
    short_description = models.TextField(_(u"Short description"), blank=True)
    description = models.TextField(_(u"Description"), blank=True)
    images = generic.GenericRelation("Image", verbose_name=_(u"Images"),
                                     object_id_field="content_id", content_type_field="content_type")

    meta_title = models.CharField(_(u"Meta title"), blank=True, default="<name>", max_length=128)
    meta_keywords = models.TextField(_(u"Meta keywords"), blank=True)
    meta_description = models.TextField(_(u"Meta description"), blank=True)

    related_products = models.ManyToManyField("self", verbose_name=_(u"Related products"), blank=True, null=True,
                                              symmetrical=False, related_name="reverse_related_products")

    accessories = models.ManyToManyField("Product", verbose_name=_(u"Acessories"), blank=True, null=True,
                                         symmetrical=False, through="ProductAccessories",
                                         related_name="reverse_accessories")

    active = models.BooleanField(_(u"Active"), default=False, db_index=True)
    creation_date = models.DateTimeField(_(u"Creation date"), auto_now_add=True)

    # Stocks
    deliverable = models.BooleanField(_(u"Deliverable"), default=True, db_index=True)
    manual_delivery_time = models.BooleanField(_(u"Manual delivery time"), default=False)
    delivery_time = models.ForeignKey("DeliveryTime", verbose_name=_(u"Delivery time"), blank=True, null=True,
                                      related_name="products_delivery_time")
    order_time = models.ForeignKey("DeliveryTime", verbose_name=_(u"Order time"), blank=True, null=True,
                                   related_name="products_order_time")
    ordered_at = models.DateField(_(u"Ordered at"), blank=True, null=True)
    manage_stock_amount = models.BooleanField(_(u"Manage stock amount"), default=False, db_index=True)
    stock_amount = models.FloatField(_(u"Stock amount"), default=0, db_index=True)

    active_packing_unit = models.BooleanField(_(u"Active packing unit"), default=False)
    packing_unit = models.FloatField(_(u"Packing unit"), blank=True, null=True)
    packing_unit_unit = models.CharField(_(u"Unit"), blank=True, max_length=30)

    # Dimension # TODO : Decide if we could implement them as properties
    weight = models.FloatField(_(u"Weight"), default=0.0)
    height = models.FloatField(_(u"Height"), default=0.0)
    length = models.FloatField(_(u"Length"), default=0.0)
    width = models.FloatField(_(u"Width"), default=0.0)

    # Standard Products
    tax = models.ForeignKey(Tax, verbose_name=_(u"Tax"), blank=True, null=True)

    # Variants
    variant_group_id = models.IntegerField(_(u"Variant Group"), blank=True, null=True, db_index=True)

    # Template to render product with
    template = models.CharField(_("Product template path"), blank=True, null=True, max_length=256)

    # others
    no_index_tag = models.BooleanField(_("No index"), default=False)
    supplier_has = models.BooleanField(_("Supplier has it"), default=False, db_index=True)

    vendor_name = models.CharField(_(u"Vendor name"), max_length=140, blank=True)

    # Manufacturer    # TODO : DECIDE : if we could use this field instead of next two fields?
    sku_manufacturer = models.CharField(blank=True, max_length=100)


    # price aggregators functions
    hotline_sku = models.CharField(_(u"hotline.ua SKU"), max_length=140, blank=True, null=True)
    yandex_sku = models.CharField(_(u"Yandex.Market SKU"), max_length=128, blank=True, null=True)

    objects = ProductManager()

    uid = models.CharField(max_length=50)

    class Meta:
        ordering = ("name", )

    def __unicode__(self):
        return "%s (%s)" % (self.name, self.slug)

    def save(self, **kwargs):
        """Overwritten to save effective_price
        use.
        """    # TODO : move this logic to pricelist app with effective_price stoed in session or cache
        self.effective_price = self.price

        super(Product, self).save(**kwargs)

    def get_absolute_url(self):
        """Returns the absolute url of the product. """
        return reverse('lfs_product', kwargs={"slug": self.slug}, current_app='lfs.catalog')

    @property
    def content_type(self):
        """Returns the content type of the product as lower string.
        """
        return u"product"

    def decrease_stock_amount(self, amount):
        """If the stock amount is managed by LFS, it decreases stock amount by
        given amount.
        """
        if self.manage_stock_amount:
            self.stock_amount -= amount
            self.save()

    def get_accessories(self):
        """Returns the ProductAccessories relationship objects - not the
        accessory (Product) objects.

        This is necessary to have also the default quantity of the relationship.
        """
        cache_key = self.cache_register_key("product:{0.id}:accessories")
        accessories = cache.get(cache_key)
        if accessories is None:
            accessories = ProductAccessories.objects.select_related('accesory', 'product').filter(product=self)
            accessories = accessories.filter(accessory__active=True).order_by('position')
            cache.set(cache_key, accessories)
        return accessories

    def has_accessories(self):
        """Returns True if the product has accessories.
        """
        return len(self.get_accessories()) > 0

    def get_accessories_to(self):
        """Returns the Product objects which relate this product as accessory.
        """
        cache_key = self.cache_register_key("product:{0.id}:accessories_to")
        accessories_to = cache.get(cache_key)

        if accessories_to is None:
            accessories_to = ProductAccessories.objects.select_related('accessory', 'product')
            accessories_to = accessories_to.filter(product__active=True).filter(accessory=self)
            cache.set(cache_key, accessories_to)
        return accessories_to

    def get_categories(self, with_parents=False, include_system=False):
        """Returns the categories of the product.
        """
        cache_key = self.cache_register_key("product-categories-{0.id}-%s-%s" % (with_parents, include_system))
        categories = cache.get(cache_key)

        if categories is not None:
            return categories

        if with_parents:
            categories = []
            categs = self.categories.all().order_by('position')
            if not include_system:
                categs = categs.exclude(is_system=True)
            for category in categs:
                while category:
                    categories.append(category)
                    category = category.parent
            categories = categories
        else:
            categories = self.categories.all().order_by('position')
            if not include_system:
                categories = categories.exclude(is_system=True)

        cache.set(cache_key, categories)
        return categories

    def get_category(self, root_category=None, include_system=False):
        """Returns the first category of a product.
        """
        root_cat_id = root_category and root_category.id or None
        cache_key = self.cache_register_key("product-category-{0.id}-%s-%s" % (root_cat_id, include_system))
        category = cache.get(cache_key, False)
        if category is False:
            category = None
            try:
                if root_category:
                    cat_tree = map(attrgetter('id'), root_category.get_all_children(include_system=include_system))
                    cat_tree.append(root_category.id)
                    category = self.categories.filter(id__in=cat_tree)[0]
                else:
                    category = self.get_categories(include_system=include_system)[0]
            except IndexError:
                category = None
            cache.set(cache_key, category)
        return category

    def get_description(self):
        """ Returns description
        """
        if self.description :
            return self.description
        else:
            return u_(u"No description")

    def get_short_description(self):
        """Returns the short description of the product.
        """
        if self.short_description :
            return self.short_description
        else:
            return u_(u"No description")

    def get_technical_description(self):
        """Returns the technical description from PropertyValue.
        """
        res = ''
        props =  lfs.properties.utils.get_properties_for_product(None, self)
        res = " / ".join((": ".join((prop.title, prop.value)) for prop in props))
        return res or u_(u"No technical description")

    def get_main_image(self):
        cache_key = self.cache_register_key('product-main-image-{0.id}')
        img = cache.get(cache_key)
        if img is None:
            img = self.images.all().order_by('position')
            img = len(img) and img[0] or None
            cache.set(cache_key, img)
        return img and img.image or None

    def get_image(self):
        """Returns the first image (the catalog image) of the product.
        """
        cache_key = self.cache_register_key('product-catalog-image-{0.id}')
        img = cache.get(cache_key)
        if img is None:
            img = self.images.filter(position__gt=-2).order_by('position')
            img = len(img) and img[0] or None
            cache.set(cache_key, img)
        return img and img.image or None

    def get_images(self):
        """Returns all images of the product, including the main image.
        """
        cache_key = self.cache_register_key("product-images-{0.id}")
        images = cache.get(cache_key)

        if images is None:
            images = self.images.all().order_by('position')
            cache.set(cache_key, images)
        return images

    def get_sub_images(self, limit=None):
        """Returns all images of the product, except the main image.
        """
        return self.get_images()[1:limit]

    def get_name(self):
        """Returns the name of the product.
        """
        return self.name

    def get_sku(self):
        """Returns the sku of the product.
        """
        return self.sku

    def get_tax_rate(self):
        """Returns the tax rate of the product.
        """
        cache_key = self.cache_register_key("tax-rate-for-product-{0.id}")
        tax_rate = cache.get(cache_key)
        if tax_rate is None:
            if self.tax_id:
                tax_rate = Tax.get_by_id(None, self.tax_id).rate         # because of extra hit to db to get tax
            else:
                tax_rate = 0.0
            cache.set(cache_key, tax_rate)
        return tax_rate

    def has_related_products(self):
        """Returns True if the product has related products.
        """
        cache_key = self.cache_register_key("has-related-products-{0.id}")
        related_products = cache.get(cache_key)

        if related_products is None:
            related_products = self.related_products.all().exists()
            cache.set(cache_key, related_products)
        return related_products

    def has_variants(self):
        """WRITE!!!!
        """
        cache_key = self.cache_register_key("has-variants-{0.id}")
        result = cache.get(cache_key)

        if result is None:
            qs = Product.objects.filter(variant_group_id=self.variant_group_id)
            qs = qs.exclude(pk = self.pk)
            if self.variant_group_id and qs.exists():
                result = True
            else:
                result = False
            cache.set(cache_key, result)
        return result


    def get_variants(self):
        """WRITE!!!!
        """
        cache_key = self.cache_register_key("get-variants-{0.id}")
        result = cache.get(cache_key)

        if result is None:
            qs = Product.objects.filter(variant_group_id=self.variant_group_id)
            qs = qs.exclude(pk = self.pk)
            result = qs
            cache.set(cache_key, result)
        return result

    def get_related_products(self):
        """Returns the related products of the product.
        """
        cache_key = self.cache_register_key("related-products-{0.id}")
        related_products = cache.get(cache_key)

        if related_products is None:
            related_products = self.related_products.all()
            cache.set(cache_key, related_products)
        return related_products

    # Dimensions
    def get_weight(self):
        """Returns weight of the product.
        """
        return self.weight

    def get_width(self):
        """Returns width of the product.
        """
        return self.width

    def get_length(self):
        """Returns length of the product.
        """
        return self.length

    def get_height(self):
        """Returns height of the product.
        """
        return self.height

    def get_packing_info(self):
        """Returns the packing info of the product as list:
        """
        return (self.packing_unit, self.packing_unit_unit)

    def is_active(self):
        """Returns the activity state of the product.
        """
        return self.active

    def is_deliverable(self, request=None):
        """Returns the deliverable state of the product.
        """
        if not self.is_available(request=request):
            return False

        return self.deliverable

    # 3rd party contracts
    def get_parent_for_portlets(self):
        """Returns the current category. This will add the portlets of the
        current category to the product portlets.
        """
        return self.get_category()

    def get_template_name(self):
        """
        method to return the path of the product template
        """
        return self.template or None

    def is_available(self, qty=0, request=None):
        """
            checks product_availability.
            if product has price less or equal to 0
            or ( manage_stock_amount is true but stock_amount less than qty)
            then product is not available and this method will return False.
            If product is available then returned value is True
        """
        from lfs.pricelist.utils import get_default_price

        if qty == 0:      # this need for copatability with pricelists api
            qty = 1

        if self.manage_stock_amount and self.get_stock_amount() < qty and not self.supplier_has:
            return False

        return bool(get_default_price(request, self) > 0)

    def get_videos(self):
        """Returns the video objects for this product.
        """
        cache_key = self.cache_register_key("product:{0.id}:videos")
        videos = cache.get(cache_key)
        if videos is None:
            videos = Video.objects.filter(product=self)
            cache.set(cache_key, videos)

        return videos

    def get_discounts(self):
        """Returns list of discount sets which has given product.
        """
        cache_key = self.cache_register_key("product:{0.id}:discounts")
        discounts = cache.get(cache_key)

        if discounts is None:
            discounts = DiscountSet.objects.filter(products=self)
            try:
                cache.set(cache_key, discounts, settings.CACHE_TIMEOUT_PRICES)
            except AttributeError:
                cache.set(cache_key, discounts)

        return discounts

    def get_files(self):
        """Returns all files for this product.
        """
        cache_key = self.cache_register_key("product:{0.id}:files")
        files = cache.get(cache_key)
        if files is None:
            ctype = ContentType.objects.get(model='product')
            files = File.objects.filter(content_type=ctype, content_id=self.id).order_by('position')
            cache.set(cache_key, files)

        return files

    def get_stock_amount(self):
        """ Returns the remainder of the products in stock with movement
            If amount < 0 then return 0
            @return: int
        """
        return Product.objects.product_info(self)['stock_amount']

Sorry for the boring and long code - but it's comprehensive information! 😃

from django-autofixture.

gregmuellegger avatar gregmuellegger commented on August 15, 2024

Cool, thanks for the quick reply. Do you know what's the field that is causing this issue? Is the related_products referencing self?

Maybe this will take me on the path of finding the issue.

from django-autofixture.

compfaculty avatar compfaculty commented on August 15, 2024

So, I changed method a little:

def process_m2m(self, instance, field):
        # check django's version number to determine how intermediary models
        # are checked if they are auto created or not.
        auto_created_through_model = False
        try:
            through = field.rel.through
            auto_created_through_model = through._meta.auto_created
        except:
            print "Exception %s" % field
            auto_created_through_model = None
        if auto_created_through_model:
            return self.process_field(instance, field)

and run it..

(venv)melihoff@melihoff-pc:~/sites/iplaza$ ./manage.py loadtestdata --traceback catalog.Product:10
Exception <django.contrib.contenttypes.generic.GenericRelation: images>

So, trouble with field

images = generic.GenericRelation("Image", verbose_name=_(u"Images"),
                                     object_id_field="content_id", content_type_field="content_type")

I hope it helps. But I stuck with speed - with default attr commit=True in create method it works too slow. I need to create 100000+ products and it takes long long time 😢 So I trying to set commit=False, and change logic to

for model, count in models:
            # if use:
            #     fixture = use(model, **kwargs)
            #     fixture.create(count)
            # else:

            instances = autofixture.create(model, count, **kwargs)
            model.objects.bulk_create(instances)

            print "model %s DONE" % model

Now its runs 2X better, but it fails if count > 10000 (abt) with memory problems

from django-autofixture.

compfaculty avatar compfaculty commented on August 15, 2024

Image class:

class Image(CacheInvalidatorMixin, models.Model):
    """An image with a title and several sizes. Can be part of a product or
    category.

    Attributes:
        - content
          The content object it belongs to.
        - title
          The title of the image.
        - image
          The image file.
        - position
          The position of the image within the content object it belongs to.
    """
    content_type = models.ForeignKey(ContentType, verbose_name=_(u"Content type"), related_name="image", db_index=True,
                                     blank=True, null=True)
    content_id = models.PositiveIntegerField(_(u"Content id"), blank=True, null=True, db_index=True)
    content = generic.GenericForeignKey(ct_field="content_type", fk_field="content_id")

    title = models.CharField(_(u"Title"), blank=True, max_length=100)
    image = ImageWithThumbsField(_(u"Image"), upload_to="images", blank=True, null=True, sizes=PRODUCT_IMAGE_SIZES)
    position = models.SmallIntegerField(_(u"Position"), default=999, db_index=True)

    # Cache Invalidator Parametrs
    _invalidate_fk_fields = ['content']

    class Meta:
        ordering = ("position", )

    def __unicode__(self):
        return self.title

from django-autofixture.

respondcreate avatar respondcreate commented on August 15, 2024

I recently ran into this same issue and it appears that the AttributeError: 'NoneType' object has no attribute '_meta' issue arises when a model has both TaggableManager AND GenericForeignKey attributes.

from django-autofixture.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.