【问题标题】:Can't disable ForeignKey referential integrity check in Django 1.9无法在 Django 1.9 中禁用 ForeignKey 引用完整性检查
【发布时间】:2016-04-18 15:01:53
【问题描述】:

我有一个包含两个实体的模型,PersonCodePersonCode 引用两次,Person 可以是代码的user,也可以是approver

我想要达到的目标如下:

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

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

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

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

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

models.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)

signals.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)

views.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

【问题讨论】:

    标签: python django django-models django-forms


    【解决方案1】:

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

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

    【讨论】:

    • 其实我可以用CharField 扩展ModelForm,然后重写save() 方法以按照建议实现登录。谢谢!
    猜你喜欢
    • 2011-10-08
    • 1970-01-01
    • 2013-12-17
    • 2011-04-03
    • 2012-01-22
    • 2011-12-24
    • 2021-03-17
    • 2014-11-25
    • 2021-12-21
    相关资源
    最近更新 更多