0

假设我有一个Form模型:

class Form(models.Model):
     name = models.TextField()
     date = models.DateField()

和各种“儿童”模型

class FormA(models.Model):
         form = models.OneToOneField(Form, on_delete=models.CASCADE)
         property_a = models.TextField()

class FormB(models.Model):
         form = models.OneToOneField(Form, on_delete=models.CASCADE)
         property_b = models.IntegerField()

class FormC(models.Model):
         form = models.OneToOneField(Form, on_delete=models.CASCADE)
         property_c = models.BooleanField()

aForm可以是 3 种形式(FormA、FormB、FormC)中的一种且仅一种。给定一个查询集Form,有什么方法可以恢复它们是什么类型的表单(A、B 或 C)?

4

3 回答 3

1

您可以通过名称或isinstance检查它。

a = FormA()
print(a.__class__) 
print(a.__class__.__name__)
print(isinstance(a, Forma)) 

输出:

<class __main__.FormA at 0xsomeaddress>
'FormA'
True

------------------- 编辑 ----------------- 好的,根据您的评论,您只想知道哪个实例分配给您的主窗体。

所以你可以做这样的事情:

if hasattr(form, 'forma'):
    # do something
elif hasattr(form, 'formb'):
    # do something else
elif hasattr(form, 'formb'):
    # do something else
于 2019-12-30T20:02:32.937 回答
1

我需要更好地了解您的实际用例,以了解这对您来说是否是一个不错的选择,但在这些情况下,我首先建议使用模型继承而不是一对一字段。你那里的代码基本上是在做多表继承已经做的事情。

首先快速阅读继承文档,并确保与 django 提供的其他选项相比,多表继承对您有意义。如果您确实希望继续使用多表继承,我建议您查看django-module-utils 中的 InheritanceManager

此时(如果使用InheritanceManager),您将能够使用isinstance.

for form in Form.objects.select_subclasses():
    if isinstance(form, FormA):
        ..... do stuff ......

这听起来可能需要付出很多额外的努力,但 IMO 它将减少移动部件(和自定义代码)并使事情更容易处理,同时仍能处理您需要的功能。

于 2019-12-30T23:06:19.733 回答
0

经过一番调查后,我想出了这个

for form in forms:
    #reduces fields to those of OneToOne types
    one_to_ones = [field for field in form._meta.get_fields() if field.one_to_one] 

    for o in one_to_ones:
        if hasattr(form,o.name):
            #do something

可能有一些缺点(可能运行时间不好),但现在可以达到它的目的。改进这一点的想法表示赞赏

于 2019-12-30T21:02:46.790 回答