Skip to main content
 首页 » 编程设计

python之无法在 Django 1.9 中禁用 ForeignKey 参照完整性检查

2024年08月22日30mengfanrong

我有一个包含两个实体的模型,Person 和 Code。 Person 被Code 引用了两次,一个Person 可以是代码的user 也可以是审批人.

我想要实现的是:

  • 如果用户提供了现有的 Person.cusman,则无需进一步操作。
  • 如果用户提供了一个未知的Person.cusman,辅助代码会查找Person 的其他属性(来自外部数据库),并创建一个新的人实体。

我已经实现了一个由 pre_save 信号触发的函数,它会即时创建丢失的 Person。只要我使用 python manage.py shell 创建一个不存在 Person 的 Code,它就可以正常工作。

但是,当我尝试使用管理表单或 CreateView 后代添加新的 Code 时,我总是在 HTML 表单上收到以下验证错误:

Select a valid choice. That choice is not one of the available choices. 

显然,在单击“保存”按钮和 Code.save() 方法之间发生了验证,但我不知道是哪一个。你能帮我在 pre_save 创建引用实体之前,我应该重写哪种方法来接受无效的外键吗?

模型.py

class Person(models.Model): 
    cusman = models.CharField( 
        max_length=10, 
        primary_key=True) 
    name = models.CharField(max_length=30) 
    email = models.EmailField() 
 
    def __unicode__(self): 
        return u'{0} ({1})'.format(self.name, self.cusman) 
 
 
class Code(models.Model): 
    user = models.ForeignKey( 
        Person, 
        on_delete=models.PROTECT, 
        db_constraint=False) 
    approver = models.ForeignKey( 
        Person, 
        on_delete=models.PROTECT, 
        related_name='approves', 
        db_constraint=False) 

信号.py

@receiver(pre_save, sender=Code) 
def create_referenced_person(sender, instance, **kwargs): 
    def create_person_if_doesnt_exist(cusman): 
        try: 
            Person = Person.objects.get(pk=cusman) 
        except Person.DoesNotExist: 
            Person = Person() 
            cr = CusmanResolver() 
            Person_details = cr.get_person_details(cusman) 
            Person.cusman = Person_details['cusman'] 
            Person.name = Person_details['name'] 
            Person.email = Person_details['email'] 
            Person.save() 
    create_Person_if_doesnt_exist(instance.user_id) 
    create_Person_if_doesnt_exist(instance.approver_id) 

View .py

class CodeAddForm(ModelForm): 
    class Meta: 
        model = Code 
        fields = [ 
            'user', 
            'approver', 
        ] 
        widgets = { 
            'user': TextInput, 
            'approver': TextInput 
        } 
 
 
class CodeAddView(generic.CreateView): 
    template_name = 'teladm/code_add.html' 
    form_class = CodeAddForm 

请您参考如下方法:

您误解了一件事:您不应该使用 TextField 来填充外键,因为 django 外键是使用下拉菜单/单选按钮来引用 id 的另一个模型中的对象。你得到的错误意味着你提供了与另一个模型中的任何 id 不匹配的错误信息(在你的情况下是 Person)。

您可以做的是:不使用ModelForm,而是使用Form。在调用 form.is_valid() 之后,您可能需要做一些额外的工作,但至少您可以根据需要编写逻辑代码。