Django将模型X与模型Y的最大n个实例相关联

2024-03-29 13:15:12 发布

您现在位置:Python中文网/ 问答频道 /正文

我在Django开发一个图书馆管理系统。你知道吗

我在app App1中有一个模型Book,在App2中有一个模型StudentEmployee。学生最多可以发行3本书,但员工可以发行任意数量的书。你知道吗

在django怎么能做到?我想我应该在书模型中使用ForeignKey,类似这样:

class Book(models.Model):
    ...
    issued_to = models.ForeignKey(Student) # <-- Student or Employee
                                           #     how do I do that?

但是如何确保max 3Book实例与单个Student实例相关呢。你知道吗


Tags: django实例模型app图书馆modelsemployee管理系统
2条回答

另一个解决方案可能是使用django信号。你知道吗

Django将在保存任何模型之前发送一个pre_save信号,这样您就可以钩住一个函数对它做出反应并执行检查。你知道吗

类似于(构建@Eliot Berriot解决方案):

from django.db.models.signals import pre_save
from django.core.exceptions import ValidationError

def validate_num_books(sender, **kwargs):
    if isinstance(sender, Student):
        max_books = 3
    elif isinstance(sender, Employee):
        max_books = 30

    books_count = sender.books.all().count()
    if books_count >= max_books:
        raise ValidationError("This person has too much books !")

pre_save.connect(validate_num_books, sender=Employee, dispatch_uid='validate_num_books')
pre_save.connect(validate_num_books, sender=Student, dispatch_uid='validate_num_books')

注意事项:

  1. 我不确定ValidationError是否会产生预期效果。希望它足以绕过正在保存的模型,但可能它不是这样工作的,或者在某些情况下是这样的,或者在其他情况下不是这样的。。。将此代码段视为实验性伪代码。

  2. 正如你可能已经从上面的一点猜到的,我不太习惯信号,仍然有点厌倦这些。这可能是完全好的,但如果一个更清洁的解决方案出现,我可能会去它,并完全避免信号。越简单越好。

  3. 与Eliot的答案相比,这个解决方案的唯一优点是它避免了继承,正如他所说的那样,继承会导致性能问题。但是,如果您避免在父类上定义字段,我认为应该可以。

如果你决定用信号做实验,start here。你知道吗

在我看来,您应该研究django模型的clean()方法。 当您尝试保存实例时,会调用它。对于您的情况,代码可能如下所示(未测试):

from django.core.exceptions import ValidationError


class Person(models.Model):
    max_books = 1

    def clean(self):
        books_count = self.books.all().count()
        if books_count >= max_books:
            raise ValidationError("This person has too much books !")


 class Book(models.Model):
    issued_to = models.ForeignKey(Person, related_name="books")

这样,您就可以创建Person模型的子类,并设置自己的max\u books限制:

class Student(Person)
    max_books = 3

class Employee(Person)
    max_books = 30

但是,要小心,因为通过使用此解决方案,您将依赖于django模型的具体继承,这可能导致performance issues。你知道吗

相关问题 更多 >