Django get_model() 模型没有属性“objects”

Lin*_*yen 1 python django django-models

我正在编写一个迁移来更新数据,我使用 get_model() 就像文档描述的那样来获取模型类,如下所示:

from django.db import migrations

def update_student(apps, schema_editor):
    # We can't import the model directly as it may be a newer
    # version than this migration expects. We use the historical version.
    CourseClass = apps.get_model('backend', 'CourseClass')
    from pprint import pprint
    pprint(vars(CourseClass))
    for course_class in CourseClass.objects.all():
        if course_class.course:
            if course_class.course.student:
                course_class.students.add(course_class.course.student)
    
    Course = apps.get_model('backend', 'Course')
    for course in Course.objects.all():
        if course.student:
            course.students.add(course.student)

class Migration(migrations.Migration):

    dependencies = [
        ('backend', '0199_auto_20211027_1026'),
    ]

    operations = [
        migrations.RunPython(update_student, migrations.RunPython.noop)
    ]
Run Code Online (Sandbox Code Playgroud)

这是我的模型和一些自定义管理器:

class CourseClass(models.Model):
    class Meta:
        db_table = 'classes'
        verbose_name = _('Class')
        verbose_name_plural = _('Classes')
    
    student_manager = StudentManager()
    teacher_manager = TeacherManager()
    objects = models.Manager()
    # other fields
Run Code Online (Sandbox Code Playgroud)

运行迁移时,我收到以下错误:

  File "/Users/admin/Library/Caches/pypoetry/virtualenvs/base.django-AnqsdXoZ-py3.8/lib/python3.8/site-packages/django/db/migrations/operations/special.py", line 190, in database_forwards
    self.code(from_state.apps, schema_editor)
  File "/Users/admin/Documents/git/icts/vietphil.hoola/backend/migrations/0200_update_student.py", line 13, in update_student
    for course_class in CourseClass.objects.all():
AttributeError: type object 'CourseClass' has no attribute 'objects
Run Code Online (Sandbox Code Playgroud)

使用 pprint 打印 CourseClass 的属性返回以下内容:

mappingproxy({'DoesNotExist': <class '__fake__.CourseClass.DoesNotExist'>,
              'MultipleObjectsReturned': <class '__fake__.CourseClass.MultipleObjectsReturned'>,
              '__doc__': 'CourseClass(id, name, date, time, duration, course, '
                         'substitute_teacher, delay_from, status, over, '
                         'class_type, canceled_by, note, teacher, '
                         'datetimestart, real_duration, screen_share, '
                         'time_end, time_start, extra_course)',
              '__module__': '__fake__',
              '_meta': <Options for CourseClass>,
              'assignment_class': <django.db.models.fields.related_descriptors.ReverseOneToOneDescriptor object at 0x112f1ce50>,
              'assignmentfile_set': <django.db.models.fields.related_descriptors.ReverseManyToOneDescriptor object at 0x112eced00>,
              'canceled_by': <django.db.models.fields.related_descriptors.ForwardManyToOneDescriptor object at 0x112f1c250>,
              'canceled_by_id': <django.db.models.fields.related_descriptors.ForeignKeyDeferredAttribute object at 0x112f1c1f0>,
              'class_type': <django.db.models.query_utils.DeferredAttribute object at 0x112f1c130>,
              'classes': <django.db.models.fields.related_descriptors.ReverseManyToOneDescriptor object at 0x112fcd1f0>,
              'classproblem_set': <django.db.models.fields.related_descriptors.ReverseManyToOneDescriptor object at 0x112f1cdf0>,
              'course': <django.db.models.fields.related_descriptors.ForwardManyToOneDescriptor object at 0x112f13ca0>,
              'course_id': <django.db.models.fields.related_descriptors.ForeignKeyDeferredAttribute object at 0x112f13c40>,
              'date': <django.db.models.query_utils.DeferredAttribute object at 0x112f13ac0>,
              'datetimestart': <django.db.models.query_utils.DeferredAttribute object at 0x112f1c4f0>,
              'delay_from': <django.db.models.query_utils.DeferredAttribute object at 0x112f13ee0>,
              'duration': <django.db.models.query_utils.DeferredAttribute object at 0x112f13b80>,
              'eps': <django.db.models.fields.related_descriptors.ManyToManyDescriptor object at 0x112f1ca30>,
              'esl_feedback': <django.db.models.fields.related_descriptors.ReverseOneToOneDescriptor object at 0x112f599a0>,
              'exam_class': <django.db.models.fields.related_descriptors.ReverseManyToOneDescriptor object at 0x112fc6610>,
              'extra_course': <django.db.models.fields.related_descriptors.ForwardManyToOneDescriptor object at 0x112f1c8e0>,
              'extra_course_id': <django.db.models.fields.related_descriptors.ForeignKeyDeferredAttribute object at 0x112f1c880>,
              'feedback': <django.db.models.fields.related_descriptors.ReverseOneToOneDescriptor object at 0x112f4eaf0>,
              'get_class_type_display': functools.partialmethod(<function Model._get_FIELD_display at 0x1032f14c0>, , field=<django.db.models.fields.CharField: class_type>),
              'homework_set': <django.db.models.fields.related_descriptors.ReverseManyToOneDescriptor object at 0x112f415b0>,
              'id': <django.db.models.query_utils.DeferredAttribute object at 0x112f13a00>,
              'ielts_feedback': <django.db.models.fields.related_descriptors.ReverseOneToOneDescriptor object at 0x112f5f790>,
              'lesson': <django.db.models.fields.related_descriptors.ReverseManyToOneDescriptor object at 0x112fe7a00>,
              'name': <django.db.models.query_utils.DeferredAttribute object at 0x112f13a60>,
              'note': <django.db.models.query_utils.DeferredAttribute object at 0x112f1c340>,
              'over': <django.db.models.query_utils.DeferredAttribute object at 0x112f1c0d0>,
              'rate': <django.db.models.fields.related_descriptors.ReverseManyToOneDescriptor object at 0x112f482b0>,
              'real_duration': <django.db.models.query_utils.DeferredAttribute object at 0x112f1c550>,
              'screen_share': <django.db.models.query_utils.DeferredAttribute object at 0x112f1c5b0>,
              'status': <django.db.models.fields.related_descriptors.ForwardManyToOneDescriptor object at 0x112f13fa0>,
              'status_id': <django.db.models.fields.related_descriptors.ForeignKeyDeferredAttribute object at 0x112f13f40>,
              'student_manager': <django.db.models.manager.ManagerDescriptor object at 0x112f1c9d0>,
              'students': <django.db.models.fields.related_descriptors.ManyToManyDescriptor object at 0x112f1c670>,
              'substitute_teacher': <django.db.models.fields.related_descriptors.ForwardManyToOneDescriptor object at 0x112f13df0>,
              'substitute_teacher_id': <django.db.models.fields.related_descriptors.ForeignKeyDeferredAttribute object at 0x112f13d90>,
              'teacher': <django.db.models.fields.related_descriptors.ForwardManyToOneDescriptor object at 0x112f1c400>,
              'teacher_id': <django.db.models.fields.related_descriptors.ForeignKeyDeferredAttribute object at 0x112f1c3a0>,
              'time': <django.db.models.query_utils.DeferredAttribute object at 0x112f13b20>,
              'time_end': <django.db.models.query_utils.DeferredAttribute object at 0x112f1c610>,
              'time_start': <django.db.models.query_utils.DeferredAttribute object at 0x112f1c7f0>,
              'video': <django.db.models.fields.related_descriptors.ReverseManyToOneDescriptor object at 0x112f5ff40>})
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,没有objects属性,我尝试使用 get_model() 与其他模型,它有objects属性。为什么 CourseClass 是唯一缺少该objects属性的类?

Lin*_*yen 5

TLDR:use_in_migrations = True如果您想在迁移文件中进行查询,请添加自定义管理器

\n

经过几个小时的搜索后,我在有关模型管理器和迁移的文档中发现了这部分

\n

https://docs.djangoproject.com/en/3.2/topics/migrations/#model-managers

\n

为了在迁移中使用自定义管理器,use_in_migrations = True需要在管理器中进行设置,因此我将管理器更改为以下内容:

\n
class StudentManager(models.Manager):\n    use_in_migrations = True\n    def student_query(self, student):\n        return super(StudentManager, self).get_queryset().filter(\n            Q(students=student) | Q(course__students=student\n        )).distinct(\'id\')\n\n\nclass TeacherManager(models.Manager):\n    use_in_migrations = True\n    def teacher_query(self, teacher):\n        return super(TeacherManager, self).get_queryset().filter(\n            Q(teacher=teacher) | Q(course__teacher=teacher)|\n            Q(substitute_teacher=teacher)).distinct(\'id\')\n\nclass MainCourseClassManager(models.Manager):\n    use_in_migrations = True\n    \nclass CourseClass(models.Model):\n    class Meta:\n        db_table = \'classes\'\n        verbose_name = _(\'Class\')\n        verbose_name_plural = _(\'Classes\')\n    \n    objects = MainCourseClassManager()\n    student_manager = StudentManager()\n    teacher_manager = TeacherManager()\n
Run Code Online (Sandbox Code Playgroud)\n

现在我的迁移使用 get_model()

\n

还从文档中注意到

\n

由于不可能序列化任意 Python 代码,因此这些历史模型不会具有您定义的任何自定义方法。但是,它们将具有相同的字段、关系managers (limited to those with use_in_migrations = True)和元选项(也有版本控制,因此它们可能与您当前的不同)。

\n