django-modelsdjango-rest-framework

Do you see any circular imports


I am getting this error with DRF, django.core.exceptions.ImproperlyConfigured: The included URLconf and I can not find the cause of it. My urls.py is afaiK configured correctly, so I'm looking for circular imports and do not see any.

I have a years app in a django project that is using DRF to build out an api. This years app has a model in it that is pretty much just used for storing 4 digit years(2020, 2021 etc).

The only other place that imports the Year model from the Year app is the User app and it uses that to allow the user to select their birth_year.

So I'm hoping some fresh eyes can help me out with this.

urls.py in years app

from rest_framework.routers import DefaultRouter
from .views import YearModelViewSet

app_name = 'years'

router = DefaultRouter()
router.register('calendar-years', YearModelViewSet, basename='calendar-year')

urlpatterns = router.urls

views.py in years app

from rest_framework.permissions import IsAdminUser
from rest_framework.viewsets import ModelViewSet

from .models import Year
from .serializers import YearSerializer

from .permissions import IsAdminOrReadOnly


class YearModelViewSet(ModelViewSet):
    permission_classes = [IsAdminUser | IsAdminOrReadOnly]
    queryset = Year.objects.all()
    serializer_class = YearSerializer
    lookup_field = 'year'

serializers.py in years app

from rest_framework import serializers

from .models import Year

class YearSerializer(serializers.ModelSerializer):
    class Meta:
        model = Year
        fields = ['dev_year_id', 'year', 'slug']

I do have a VehicleYear class model in a vehicles app that does import the Year model from that class:

models.py from vehicles app

from years.models import Year

class VehicleYear(models.Model):
    model_year = models.OneToOneField(Year, ...)

I am using OneToOne here because I figured I would just use the year data from the years app to supply the VehicleYear with 4 digit years. Maybe my thinking here is wrong?

The only other thing I can think of is that I do have a Vehicle app that does have a model of Vehicle and that class model of Vehicle has an attribute of year. I'm not sure if maybe I'm confusing Django with an ill-advised attribute name?

class Vehicle(models.Model):
  dev_vehicle_id = models.UUIDField(...)
  year = models.ForeignKey(VehicleYear, ...)  # could this line be causing the error?

Edit, full traceback:

Traceback (most recent call last):
  File "/home/xxx/projects/yyyy/zzzzz/backend/venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 720, in url_patterns
    iter(patterns)
TypeError: 'module' object is not iterable

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/xxx/projects/yyyy/zzzzz/backend/manage.py", line 22, in <module>
    main()
  File "/home/xxx/projects/yyyy/zzzzz/backend/manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "/home/xxx/projects/yyyy/zzzzz/backend/venv/lib/python3.12/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line
    utility.execute()
  File "/home/xxx/projects/yyyy/zzzzz/backend/venv/lib/python3.12/site-packages/django/core/management/__init__.py", line 436, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/xxx/projects/yyyy/zzzzz/backend/venv/lib/python3.12/site-packages/django/core/management/base.py", line 416, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/home/xxx/projects/yyyy/zzzzz/backend/venv/lib/python3.12/site-packages/django/core/management/base.py", line 457, in execute
    self.check(**check_kwargs)
  File "/home/xxx/projects/yyyy/zzzzz/backend/venv/lib/python3.12/site-packages/django/core/management/base.py", line 492, in check
    all_issues = checks.run_checks(
                 ^^^^^^^^^^^^^^^^^^
  File "/home/xxx/projects/yyyy/zzzzz/backend/venv/lib/python3.12/site-packages/django/core/checks/registry.py", line 89, in run_checks
    new_errors = check(app_configs=app_configs, databases=databases)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/xxx/projects/yyyy/zzzzz/backend/venv/lib/python3.12/site-packages/django/core/checks/urls.py", line 44, in check_url_namespaces_unique
    all_namespaces = _load_all_namespaces(resolver)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/xxx/projects/yyyy/zzzzz/backend/venv/lib/python3.12/site-packages/django/core/checks/urls.py", line 74, in _load_all_namespaces
    namespaces.extend(_load_all_namespaces(pattern, current))
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/xxx/projects/yyyy/zzzzz/backend/venv/lib/python3.12/site-packages/django/core/checks/urls.py", line 63, in _load_all_namespaces
    url_patterns = getattr(resolver, "url_patterns", [])
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/xxx/projects/yyyy/zzzzz/backend/venv/lib/python3.12/site-packages/django/utils/functional.py", line 47, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
                                         ^^^^^^^^^^^^^^^^^^^
  File "/home/xxx/projects/yyyy/zzzzz/backend/venv/lib/python3.12/site-packages/django/urls/resolvers.py", line 728, in url_patterns
    raise ImproperlyConfigured(msg.format(name=self.urlconf_name)) from e
django.core.exceptions.ImproperlyConfigured: The included URLconf '<module 'years' from '/home/xxx/projects/yyyy/zzzzz/backend/years/__init__.py'>' does not appear to have any patterns in it. If you see the 'urlpatterns' variable with valid patterns in the file then the issue is probably caused by a circular import

Edit 2, Year model:

class Year(models.Model):
    dev_year_id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) # sqlite
    year = models.SmallIntegerField(unique=True, validators=[
                            MinLengthValidator(4), MaxLengthValidator(4)])
    slug = models.SlugField(unique=True, validators=[
                            MinLengthValidator(4), MaxLengthValidator(4)])
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.year

    class Meta:
        db_table = 'year'
        ordering = ['-year']
        verbose_name = _('Year')
        verbose_name_plural = _('Years')

Solution

  • It appears you have somewhere in the urls.py of your code an:

    include('years')

    whereas it should be:

    include('years.urls')