Python Django-将模型X关联到模型Y的最大n个实例

Python Django-将模型X关联到模型Y的最大n个实例,python,django,django-models,Python,Django,Django Models,我正在Django开发一个图书馆管理系统 我在appApp1中有一本模型书,在App2中有模型学生和员工。学生最多可以发行3本书,但员工可以发行任意数量的书 在django怎么能做到这一点?我想我应该在“图书模型”中使用ForeignKey,比如: class Book(models.Model): ... issued_to = models.ForeignKey(Student) # <-- Student or Employee

我正在Django开发一个图书馆管理系统

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

在django怎么能做到这一点?我想我应该在“图书模型”中使用
ForeignKey
,比如:

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

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

通过这种方式,您可以创建Person模型的子类,并设置您自己的max_books限制:

class Student(Person)
    max_books = 3

class Employee(Person)
    max_books = 30

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

另一种解决方案可能是使用django信号

Django将在保存任何模型之前发送一个
pre_save
信号,因此您可以钩住一个函数对其作出反应并执行检查

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

注:

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

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

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


  • 如果您决定尝试使用信号,.

    这显然是一种业务逻辑。在DB级别强制执行业务规则被认为是一个坏主意,因为BL往往会频繁更改,而DB没有那么灵活。所以我应该保留max 3部分吗?好的,我想这是个好主意。但是我如何管理
    ForeignKey
    Student
    Employee
    的事情呢?我是否应该创建一个像
    终端用户
    这样的通用模型,并将其继承到
    学生
    员工
    ?还有其他方法吗?读了django的文档后,你会想到什么,用一个
    pre_save
    信号,你可以检查模型的类型来决定允许多少本书?不太像Python,可能有点混乱,但这样可以避免继承的需要。@astrognocci我认为你的答案是可行的,你应该把它作为答案提交,并附上一段代码来解释。实际上,现在我放弃了控制可以发行多少本书的想法。我现在关注如何处理我在上面最后一次评论中描述的问题。我应该使用
    EndUser
    abstract类和
    GenericForeignKey
    还是不在
    Book
    中使用
    ForeignKey(EndUser)
    。哪一个更好(更容易)?嗯,更容易的是具体的继承。更好是非常主观的,取决于您的需求:数据库性能对您的项目重要吗?如果是的话,你将不得不寻找其他东西或使用第三方应用程序,如django多态,来优化你的查询。
    class Student(Person)
        max_books = 3
    
    class Employee(Person)
        max_books = 30
    
    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')