有一个模型叫
Borrow
。在 BorrowLine
模型中,ForeignKey 是用 related_name lines
定义的。我为 BorrowAdmin
模型写下 BorrowLineInline
和 Borrow
。在 BorrowAdmin
类中,我使用了 save_model
函数,如下所示:
def save_model(self, request, obj, form, change):
obj.save()
print(obj.lines)
return super(BorrowAdmin, self).save_model(request, obj, form, change)
但是当我在 Django 管理中添加
Borrow
模型的实例时,控制台中会打印以下行:
borrow.BorrowLine.None
我无法访问任何 BorrowLine
字段。例如,它的字段之一是 book,但是当我调用它时,它给出了以下错误:
'RelatedManager' object has no attribute 'book'
我该如何解决这个问题并访问类字段?
我的代码:
class Borrow(models.Model):
student = models.ForeignKey('student.Student', on_delete=models.CASCADE, related_name='borrow')
created_time = models.DateField(auto_now_add=True)
delivery_time = models.DateField(default=date.today() + timedelta(days=7), validators=[delivery_time_validator])
delivered = models.BooleanField(default=False)
def __str__(self):
return str(self.student)
class BorrowLine(models.Model):
borrow = models.ForeignKey('Borrow', on_delete=models.CASCADE, related_name='lines')
book = models.ForeignKey('book.Book', on_delete=models.CASCADE, related_name='lines')
def __str__(self):
return f'{self.borrow} -> {self.book}'
def clean(self):
book = self.book
if not book.is_available:
raise ValidationError(f'The book {book.title} is not available.')
class BorrowLineInline(admin.TabularInline):
model = BorrowLine
extra = 1
max_num = 3
autocomplete_fields = ('book',)
@admin.register(Borrow)
class BorrowAdmin(admin.ModelAdmin):
inlines = (BorrowLineInline,)
list_display = ('student', 'created_time', 'delivery_time', 'delivered')
search_fields = ('student__first_name', 'student__last_name', 'lines__book__title')
list_filter = ('student__class_type', 'delivered', 'created_time', 'delivery_time')
autocomplete_fields = ('student',)
def add_view(self, request, form_url="", extra_context=None):
self.fields = ('student', 'delivery_time')
return super(BorrowAdmin, self).add_view(request, form_url=form_url, extra_context=extra_context)
def change_view(self, request, object_id, form_url="", extra_context=None):
self.fields = ('student', 'delivery_time', 'delivered')
return super(BorrowAdmin, self).change_view(request, object_id, form_url=form_url, extra_context=extra_context)
def save_model(self, request, obj, form, change):
obj.save()
print(obj.lines.book)
# Do something
return super(BorrowAdmin, self).save_model(request, obj, form, change)
我还使用了
post_save
和 pre_save
等信号来代替 save_model
,但它们也有同样的错误并返回 None。
经理总是打印
app_name.ModelName.None
,你需要与QuerySet
一起工作,所以:
def save_model(self, request, obj, form, change):
obj.save()
print(obj.lines.all())
return super().save_model(request, obj, form, change)
话虽如此,它不会显示lines
,因为它会首先保存
obj
,然后保存它的多对多关系。因此,您可以在保存整个模型之后检查关系:
def save_model(self, request, obj, form, change):
return super().save_model(request, obj, form, change)
print(obj.lines.all())
:自PEP-3135 [pep] 起,如果第一个参数是定义方法的类,第二个参数是方法,则无需带参数调用
super(…)
函数的第一个参数(通常为self
)。