2

I am working on an oscar project for India and now I want to apply taxes on products. I have followed the docs for applying taxes over prices and availability , forked the partner app. When I specified rate=('0.20'), it applied a tax of 20 % on all products, now I want to make it dynamic.

So I went through the code for strategy.FixedRateTax,and I tried implementing the code for get_rate(), since it gets called for all the products.

How I want to make it dynamic is, based on the product category I want to apply the tax on the product which is in get_rate().

So I created a model in core/models.py

class CategoryTax(models.Model):
    category = models.OneToOneField(Category, on_delete=models.CASCADE, unique=True)
    gst_tax = models.DecimalField(max_digits=11, decimal_places=4, null=True, default=0)

    def __str__(self):
        return "%s" % self.category

Here importing of the category model is working fine,but when I go to the strategy.py and import models from core, and the other apps, django gives an exception.

My forked_apps/partner/strategy.py is:

from decimal import Decimal as D
from oscar.apps.partner import strategy, prices
from django.conf import settings

from oscar.core.loading import get_model
from core.models import CategoryTax

Partner = get_model('partner', 'Partner')
Category = get_model('catalogue', 'Category')
Product = get_model('catalogue', 'Product')
ProductCategory = get_model('catalogue', 'ProductCategory')


class Selector(object):
    """
    Custom selector to return a India-specific strategy that charges GST
    """

    def strategy(self, request=None, user=None, **kwargs):
        return IndiaStrategy()


class IncludingVAT(strategy.FixedRateTax):
    """
    Price policy to charge VAT on the base price
    """
    # We can simply override the tax rate on the core FixedRateTax.  Note
    # this is a simplification: in reality, you might want to store tax
    # rates and the date ranges they apply in a database table.  Your
    # pricing policy could simply look up the appropriate rate.

    # The Tax rate applied here is 3 % GST Now
    rate = D(settings.SITE_GST)

    def get_rate(self, product, stockrecord):
        """
        This method serves as hook to be able to plug in support for varying tax rates
        based on the product.

        TODO: Needs tests.
        """

        try:
            product = Product.objects.get(id=product.id)
            prod_cat = ProductCategory.objects.get(product=product)
            cat = Category.objects.get(id=prod_cat.category_id)

            cat_tax = CategoryTax.objects.get(category=cat)
            print("The Cat Tax: ", cat_tax)

        except Exception as e:
            print(e)
        return self.rate
class IndiaStrategy(strategy.UseFirstStockRecord, IncludingVAT,
             strategy.StockRequired, strategy.Structured):
    """
    Typical India strategy for physical goods.

    - There's only one warehouse/partner so we use the first and only stockrecord
    - Enforce stock level.  Don't allow purchases when we don't have stock.
    - Charge Indian GST on prices.  Assume everything is standard-rated.
    """

The Exception that I get is:

django.core.exceptions.AppRegistryNotReady: Models aren't loaded yet.

and also: ImportError: cannot import name 'CategoryTax'

Do suggest me any method possible that I can use to make this work.

I am using Django 2.1.3, Django Oscar 1.6.4

The entire error stack trace:

Unhandled exception in thread started by <function check_errors.<locals>.wrapper at 0x7f623e655400>
Traceback (most recent call last):
  File "/home/venvs/test/lib/python3.6/site-packages/oscar/core/loading.py", line 296, in get_model
    return apps.get_model(app_label, model_name)
  File "/home/venvs/test/lib/python3.6/site-packages/django/apps/registry.py", line 195, in get_model
    self.check_models_ready()
  File "/home/venvs/test/lib/python3.6/site-packages/django/apps/registry.py", line 137, in check_models_ready
    raise AppRegistryNotReady("Models aren't loaded yet.")
django.core.exceptions.AppRegistryNotReady: Models aren't loaded yet.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/venvs/test/lib/python3.6/site-packages/oscar/core/loading.py", line 296, in get_model
    return apps.get_model(app_label, model_name)
  File "/home/venvs/test/lib/python3.6/site-packages/django/apps/registry.py", line 195, in get_model
    self.check_models_ready()
  File "/home/venvs/test/lib/python3.6/site-packages/django/apps/registry.py", line 137, in check_models_ready
    raise AppRegistryNotReady("Models aren't loaded yet.")
django.core.exceptions.AppRegistryNotReady: Models aren't loaded yet.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/venvs/test/lib/python3.6/site-packages/django/utils/autoreload.py", line 225, in wrapper
    fn(*args, **kwargs)
  File "/home/test/abhushan/lib/python3.6/site-packages/django/core/management/commands/runserver.py", line 109, in inner_run
    autoreload.raise_last_exception()
  File "/home/venvs/test/lib/python3.6/site-packages/django/utils/autoreload.py", line 248, in raise_last_exception
    raise _exception[1]
  File "/home/venvs/test/lib/python3.6/site-packages/django/core/management/__init__.py", line 337, in execute
    autoreload.check_errors(django.setup)()
  File "/home/venvs/test/lib/python3.6/site-packages/django/utils/autoreload.py", line 225, in wrapper
    fn(*args, **kwargs)
  File "/home/venvs/test/lib/python3.6/site-packages/django/__init__.py", line 24, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "/home/venvs/test/lib/python3.6/site-packages/django/apps/registry.py", line 112, in populate
    app_config.import_models()
  File "/home/venvs/test/lib/python3.6/site-packages/django/apps/config.py", line 198, in import_models
    self.models_module = import_module(models_module_name)
  File "/home/venvs/test/lib/python3.6/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 994, in _gcd_import
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 678, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/home/venvs/test/project/core/models.py", line 8, in <module>
    Category = get_model('catalogue', 'Category')
  File "/home/venvs/test/lib/python3.6/site-packages/oscar/core/loading.py", line 308, in get_model
    import_module('%s.%s' % (app_config.name, MODELS_MODULE_NAME))
  File "/home/venvs/test/lib/python3.6/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 994, in _gcd_import
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 678, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/home/venvs/test/lib/python3.6/site-packages/oscar/apps/catalogue/models.py", line 4, in <module>
    from oscar.apps.catalogue.abstract_models import *  # noqa
  File "/home/venvs/test/lib/python3.6/site-packages/oscar/apps/catalogue/abstract_models.py", line 35, in <module>
    Selector = get_class('partner.strategy', 'Selector')
  File "/home/venvs/test/lib/python3.6/site-packages/oscar/core/loading.py", line 59, in get_class
    return get_classes(module_label, [classname], module_prefix)[0]
  File "/home/venvs/test/lib/python3.6/site-packages/oscar/core/loading.py", line 69, in get_classes
    return class_loader(module_label, classnames, module_prefix)
  File "/home/venvs/test/lib/python3.6/site-packages/oscar/core/loading.py", line 141, in default_class_loader
    local_module = _import_module(local_module_label, classnames)
  File "/home/venvs/test/lib/python3.6/site-packages/oscar/core/loading.py", line 182, in _import_module
    return __import__(module_label, fromlist=classnames)
  File "/home/test/forked_apps/partner/strategy.py", line 16, in <module>
    Category = get_model('catalogue', 'Category')
  File "/home/venvs/test/lib/python3.6/site-packages/oscar/core/loading.py", line 311, in get_model
    return apps.get_registered_model(app_label, model_name)
  File "/home/venvs/test/lib/python3.6/site-packages/django/apps/registry.py", line 270, in get_registered_model
    "Model '%s.%s' not registered." % (app_label, model_name))
LookupError: Model 'catalogue.Category' not registered.
Sammy J
  • 1,048
  • 10
  • 28
  • You can try delayed loading for your `CategoryTax` model (either with Oscar's `get_model` or [Django's](https://stackoverflow.com/a/4881693/2689986)) instead of the direct import. – shad0w_wa1k3r Jan 06 '19 at 08:34
  • Hi, I have tried giving, `CategoryTax = get_model('core', 'CategoryTax')` and then tried running the server, but then I still get the error 'django.core.exceptions.AppRegistryNotReady: Models aren't loaded yet. During handling of the above exception, another exception occurred: LookupError: Model 'catalogue.Category' not registered. ' – Sammy J Jan 07 '19 at 13:30

1 Answers1

2

You have a circular import that is causing this to fail. In strategy.py you are trying to load the Category model, and in Oscar's catalogue/abstract_models.py it is in turn trying to load the Selector model (for reasons that I am not clear on - think that is actually a bug and will look into it separately).

I think it should work if you move the imports in your selector.py to inside the method that requires them:

def get_rate(self, product, stockrecord):
    Category = get_model('catalogue', 'Category')
    Product = get_model('catalogue', 'Product')
    ProductCategory = get_model('catalogue', 'ProductCategory')
    # do your logic here
solarissmoke
  • 30,039
  • 14
  • 71
  • 73
  • Hi, I tried doing the above method suggested by you, but it still gives the same exception with another one being, `LookupError: Model 'catalogue.Category'` not registered.I guess the`Partner = get_model('partner', 'Partner')` gets imported, but the `Category = get_model('catalogue', 'Category')` isn't imported? – Sammy J Jan 07 '19 at 13:28
  • I thought the problem was with my model, but I tried querying the model using shell and also inserting data using the admin too and it worked fine for me – Sammy J Jan 07 '19 at 13:38
  • I can't see it from what you have posted, but most likely the issue is with a circular import somewhere in your code. Can you post the full stack trace? – solarissmoke Jan 07 '19 at 14:14
  • Hi, I have updated the stack trace to the question now. – Sammy J Jan 08 '19 at 10:12
  • I've edited the answer to address the issue that the stack trace shows - try that? – solarissmoke Jan 08 '19 at 11:09