我有一个包含两个实体的模型,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() 之后,您可能需要做一些额外的工作,但至少您可以根据需要编写逻辑代码。
