2015-05-20 16 views
7

Tôi có mô hình này:ForeignKey lĩnh vực liên quan đến mô hình trừu tượng trong Django

class BaseModel(models.Model): 
    .... 

    class Meta: 
     abstract = True 


class ModelA(BaseModel): 
    .... 

class ModelB(BaseModel): 
    .... 


class MyExtModel(models.Model) 
    myfield = models.ForeignKey(BaseModel) 

Nhưng điều này là không đúng bởi vì tôi có BaseModel như Abstract. Infact Tôi gặp lỗi khi thử lệnh makemigration.

Lỗi này là:

ERRORS: 
myapp.MyExtModel.myfield: (fields.E300) Field defines a relation with model 'BaseModel', which is either not installed, or is abstract. 

Có cách nào để sử dụng một mô hình cơ sở trừu tượng?

Tôi cũng cố gắng sử dụng:

myfield = models.ForeignKey(BaseModel, related_name="%(app_label)s_%(class)s_related") 

Trả lời

6

Không thể cài đặt Khóa ngoại tuyến cho các mô hình trừu tượng ở Django. Tuy nhiên, bạn có thể cài đặt Khóa ngoại cho một lớp cơ sở không trừu tượng. Giới hạn duy nhất là quan hệ đảo ngược khóa ngoài sẽ trả về các cá thể lớp cơ sở. Bạn có thể phá vỡ giới hạn này bằng cách sử dụng django-polymorphic.

Django đa hình cho phép bạn truy vấn các đối tượng lớp cơ sở nhưng lấy các trường hợp lớp trẻ:

>>> Project.objects.create(topic="Department Party") 
>>> ArtProject.objects.create(topic="Painting with Tim", artist="T. Turner") 
>>> ResearchProject.objects.create(topic="Swallow Aerodynamics", supervisor="Dr. Winter") 

>>> Project.objects.all() 
[ <Project:   id 1, topic "Department Party">, 
    <ArtProject:  id 2, topic "Painting with Tim", artist "T. Turner">, 
    <ResearchProject: id 3, topic "Swallow Aerodynamics", supervisor "Dr. Winter"> ] 

Để sử dụng django đa hình, bạn chỉ cần khai báo mô hình của bạn với đa hình mẫu như lớp cơ sở:

from django.db import models 
from polymorphic.models import PolymorphicModel 

class ModelA(PolymorphicModel): 
    field1 = models.CharField(max_length=10) 

class ModelB(ModelA): 
    field2 = models.CharField(max_length=10) 

class ModelC(ModelB): 
    field3 = models.CharField(max_length=10) 

Khóa ngoại cũng sẽ trả về các phiên bản lớp con, đó là những gì bạn cần tôi giả định:

# The model holding the relation may be any kind of model, polymorphic or not 
class RelatingModel(models.Model): 
    many2many = models.ManyToManyField('ModelA') # ManyToMany relation to a polymorphic model 

>>> o=RelatingModel.objects.create() 
>>> o.many2many.add(ModelA.objects.get(id=1)) 
>>> o.many2many.add(ModelB.objects.get(id=2)) 
>>> o.many2many.add(ModelC.objects.get(id=3)) 

>>> o.many2many.all() 
[ <ModelA: id 1, field1 (CharField)>, 
    <ModelB: id 2, field1 (CharField), field2 (CharField)>, 
    <ModelC: id 3, field1 (CharField), field2 (CharField), field3 (CharField)> ] 

Hãy xem xét các truy vấn này sẽ là slightly less performant.

+0

Tôi không biết PolymorphicModel ... có lẽ điều này có thể giúp tôi. Tôi không hiểu một khía cạnh: PolymorphicModel dựa trên GenericRelation? Khi nào cần sử dụng GenericRelation (loại nội dung) thay vì PolymorphicModel? Có lẽ câu hỏi này nằm ngoài ngữ cảnh của câu hỏi ban đầu của tôi ... – Safari

+1

Quan hệ chung không liên quan đến các mô hình Đa hình. Quan hệ chung là hữu ích cho các loại mô hình chung mà bạn có trong các ứng dụng của bạn và có chìa khóa nước ngoài cho các mô hình khác nhau về cơ bản. Tôi có một mô hình Hình ảnh chung trong ứng dụng của mình và cả hai mô hình Sự kiện và Nhóm có thể có Hình ảnh. Đây là một mối quan hệ chung chung. Tôi cũng có một mô hình InternationalTeam kế thừa từ Nhóm, và sau đó các Nhóm cũng sẽ có Hình ảnh, mà không cần phải xác định rõ ràng trong mô hình. –

3

Khi tôi phải đối mặt với một tình huống như thế mà tôi phải làm ForeignKeys với các mô hình khác nhau tôi chọn để sử dụng GenericForeignKey bạn có thể kiểm tra tài liệu chính thức ở đây: Django ContentTypes: Generic Relations

các tài liệu giải thích khá tốt như thế nào để sử dụng nó:

from django.db import models 
from django.contrib.contenttypes.fields import GenericForeignKey 
from django.contrib.contenttypes.models import ContentType 

class TaggedItem(models.Model): 
    tag = models.SlugField() 
    content_type = models.ForeignKey(ContentType) 
    object_id = models.PositiveIntegerField() 
    content_object = GenericForeignKey('content_type', 'object_id') 

    def __str__(self):    # __unicode__ on Python 2 
     return self.tag 
  • Trường content_type cửa hàng mô hình rằng chìa khóa nước ngoài generic được trỏ đến

  • Trường object_id cửa hàng ID của chính nước ngoài,

  • Trường content_object giúp bạn truy cập trực tiếp đến đối tượng liên quan dựa trên 2 trường khác

Đây không phải là giải pháp tốt nhất nhưng nó giúp tôi tiết kiệm trong một số dự án

Ví dụ về sử dụng nó:

from django.contrib.auth.models import User 
guido = User.objects.get(username='Guido') 
t = TaggedItem(content_object=guido, tag='bdfl') 
t.save() 
t.content_object 
<User: Guido> 
1

Ngoài các câu trả lời tốt đẹp với GenericForeignKey, mà tôi không khá quen thuộc, thỉnh thoảng (chỉ thỉnh thoảng, bất cứ khi nào có thể), thì rất đáng để đơn giản hóa mô hình của bạn bằng cách sử dụng one- một mối quan hệ với mô hình 'cơ bản' của bạn.

Làm cho việc quản lý khóa ngoại vi dễ dàng hơn sau đó. Nếu tôi nhớ rõ, khoá ngoại trên một lớp trừu tượng là không thể.

Các vấn đề liên quan