2016-09-26 36 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

相關問題