如何在Django中为ManyToManyField设置默认值

时间:2020-10-07 14:13:50

标签: python django django-models default-value manytomanyfield

编辑-更新了models.py models.py:

from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver

class Department(models.Model):
    departmentName = models.CharField(max_length=100)

    def __str__(self):
        return self.departmentName

class Designation(models.Model):
    designationName = models.CharField(max_length=100, null=True)

    def __str__(self):
        return self.designationName
 
class Employee(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField(unique=True, blank=False)
    department = models.ManyToManyField(Department, blank=True)
    designation = models.ForeignKey(Designation, null=True, on_delete=models.SET_NULL)

    def __str__(self):
        return self.name
    
    def departments(self):
        return ",".join([d.departmentName for d in self.department.all()])

#Using post receiver signal as suggested by @Daniel in answer and comments

@receiver(post_save, sender=Employee, dispatch_uid='set_department')
def SetDefaultDeparment(**kwargs):

    employee = kwargs['instance']
       
    if not employee.department.all(): 

        resource_pool = Department.objects.get(departmentName="RP")

        employee.department.add(resource_pool)
        employee.save()
                 

我的查询/要求:员工和部门通过M2M链接。我设置blank = True以克服没有选择任何部门的形式验证。 (null = True似乎不适用于M2M)

比方说,

方案1: 在创建新的Emp时,如果没有提供部门,则默认情况下应将其设置为RP(资源池)。

场景2: 现有的Emp来自人力资源部门;假设由于某种原因HR部门被删除或Emp被踢出,现在Emp没有与其关联的部门,则默认情况下应将其移至RP(资源池)!

如何在Django中安排默认的部门RP,以使两种情况都通过!!

预先感谢:)

少年

1 个答案:

答案 0 :(得分:1)

如此处The right way to set the default value of a ManyToMany field in django所示,您可以选择几种方式。

这是通过覆盖save方法来实现的:

class Employee(models.Model):

    ...
    
    def save(self): 

        # set department if field is empty:        
        if not self.department.all(): 

            # get the resource pool department:
            resource_pool = Department.objects.get(name='Resource Pool')

            # add to instance:
            self.department.add(resource_pool)
        
        super(Employee, self).save(*args, **kwargs)

以下是使用post_save接收器的方法:

from django.db.models.signals import post_save
from django.dispatch import receiver

# this decorator will execute the function after an Employee is saved:
@receiver(post_save, sender=Employee, dispatch_uid='set_department')
def SetDefaultDeparment(**kwargs):
    
    ''' sets a default department for an Employee where needed '''
    
    # unpack kwargs:
    employee = kwargs['instance']

    # set department if field is empty:        
    if not employee.department.all(): 

         # get the resource pool department:
         resource_pool = Department.objects.get(name='Resource Pool')

         # add to instance:
         employee.department.add(resource_pool)
         employee.save()
相关问题