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属性的类?
TLDR:use_in_migrations = True如果您想在迁移文件中进行查询,请添加自定义管理器
经过几个小时的搜索后,我在有关模型管理器和迁移的文档中发现了这部分
\nhttps://docs.djangoproject.com/en/3.2/topics/migrations/#model-managers
\n为了在迁移中使用自定义管理器,use_in_migrations = True需要在管理器中进行设置,因此我将管理器更改为以下内容:
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()\nRun Code Online (Sandbox Code Playgroud)\n现在我的迁移使用 get_model()
\n还从文档中注意到
\n由于不可能序列化任意 Python 代码,因此这些历史模型不会具有您定义的任何自定义方法。但是,它们将具有相同的字段、关系managers (limited to those with use_in_migrations = True)和元选项(也有版本控制,因此它们可能与您当前的不同)。