Question

First off, it is not about circular Model references. I could find a lot of answers about those.

I am building an app that let's you easily define reminders in your settings. Therefore the REMINDERS setting looks like this:

settings

REMINDERS = [
    {
        'reminder_id': 'my-id',
        'reminder_class': 'students.reminders.ExpiredAvailabilityEmailReminder',
    },
]

In this app (reminders), I provide a base class for these reminders, that has some default behaviour in it. To define a reminder, the only thing I have to do is for example:

students_app/reminders.py

from reminders.base_reminders import ReminderEmail
from .models import Student


class ExpiredAvailabilityEmailReminder(ReminderEmail):
    template_name = 'students/emails/setting_expired.html'

    def get_queryset(self):
        return Student.objects.filter(
                    is_active=True,
                    setting_expired__lt=datetime.date.today())

reminders_app/management/commands/send_reminders.py

The management command imports this reminder_class-string in handle with django.utils.module_loading.import_by_path, but this fails with:

django.core.exceptions.ImproperlyConfigured: Error importing module studenten.reminders: "No module named base_reminders"

Because it becomes a circular reference. How can I provide the users of my app with an subclassable base class, without running into this problem?

Thanks.

Was it helpful?

Solution

This problem relates to the default import order in Python 2. If you are in students_app/reminders.py and you have from reminders.base_reminders import ReminderEmail it isn't clear whether the reminders module is referring to itself or your app which is also called reminders. To fix this you can use from __future__ import absolute_import in Python 2.5+ (or use Python 3 where this is the default)

from __future__ import absolute_import
from reminders.base_reminders import ReminderEmail

which will ensure that the reminders import uses the reminders app rather than the relative reminders module.

The other fix is a documentation one which is to not encourage people to name their module reminders to avoid this naming conflict.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top