2016-09-26 55 views
1

我试图改变我创建的应用程序,以便它可以重用。它基于使用该应用的网站将继承的单一模型。就目前而言,我的不可重复使用的版本有以下几种结构:如何在Django中使用基类

# models.py 
class Document(models.Model): 
    contents = models.TextField() 
    date = models.DateTimeField() 

# views.py 
from .models import SiteModel 
# ... 
class MyView(ListView): 
    def some_method(self, list_of_pks): 
     model_vals = Document.objects.filter(pk__in = list_of_pks).values() 

def perform_action(request): 
    obj_pk = request.POST.get('obj_pk') 
    obj = Document.objects.filter(pk = obj_pk) 

    MySignal.send(sender=Document, instance = obj) 

#etc, etc 

这很好。但是我的使用案例需要不同类型的Document,每个站点一个,其中会有其他未知的字段。基于阅读abstract base classes的文档,我认为一个合理的解决办法是这样的:

# models.py for the app 
class BaseDocument(models.Model): 
    contents = models.TextField() 

    class Meta: 
     abstract = True 

# models.py for a hypothetical site using the app 
class SiteDocument(myapp.BaseDocument): 
    date = models.DateTimeField() 
    # other site-specific fields 

我不明白的是,如何在参考模型中应用程序的views.pyforms.py,等我知道BaseDocument.objects.all()例如,由于它没有连接到数据库,它不会返回任何东西。相反,我不能有Document.objects.all(),因为Document还没有创建,并且是特定于每个站点。抽象基类是不是正确的解决方案,如果是的话,是什么?

编辑:

它看起来像使用OneToOneField可能是最适合我的使用情况下,虽然这看起来排除继承了父方法和BaseDocument.objects.all()不会列出它的所有儿童。

另外,我想知道是否可以在我的抽象基类中添加get_document_model()方法,样式为get_user_model()

回答

0

我结束了中提到的解决方案去我的编辑,即创建一个get_document_model()方法灵感get_user_model()。这给了我完全想要的行为。

# models.py in app1 
from django.db import models 
from django.apps import apps as django_apps 

class BaseDocument(models.Model): 
    contents = models.TextField() 

    class Meta: 
     abstract = True 

    def get_document_model(): 
     # exception handling removed for concision's sake 
     return django_apps.get_model(settings.DOCUMENT_MODEL) 

# models.py in app2 
from django.db import models 
from app1.models import BaseDocument 

class SiteDocument(BaseDocument): 
    date = models.DateTimeField() 

整个views.py和其他地方,我改变的东西,会一直形式Document.objects.all()BaseDocument().get_document_model().objects.all()

0

你不能直接查询你的抽象类,因为它们不会有管理器,只有继承的类。如果您确实必须执行继承,则可以使用具体的基本模型并以每个查询的加入为代价继承它。

认真考虑这是否真的有必要,或者如果您可以以更通用的方式表示您的数据。模型让继承看起来很容易,但它们并不神奇。有非常真实的性能和复杂性考虑。

这可能是因为添加type场到模型

class Document(models.Model): 
    DOCUMENT_TYPES = ['site', 'another', 'whatever'] 

    document_type = models.CharField(choices=DOCUMENT_TYPES) 
    ... 

有关抽象VS具体类和查询更多信息一样方便,请访问How to query abstract-class-based objects in Django?

+0

我并不是特别致力于继承或抽象基类,我只是觉得这是合适的解决方案。这可能是一个XY问题,并且我没有说明我的用例。使用该应用程序的网站只会使用一个“文档”,但我们不会提前知道它的字段。我想我的问题可以改写为:我如何在我的应用程序中引用模型,知道任何给定的站点将继承并扩展该模型? – HoHo

+0

我知道我不需要'BaseDocument'是具体的,所以连接看起来没有必要,我可以使用ForeignKey来引用一个可能的孩子,然后在'views'做类似'BaseDocument.doc_child.objects.all ()'? – HoHo

+0

这些文档是否处于实际层次结构中,还是只是在寻找伪继承的方式?除非你真的可以证明它,否则你可能根本不需要继承。 – Soviut