2013-07-19 5 views
3

После многого поиска и поиска нескольких методов, которые позволят мне это сделать (и даже меньше с рабочими примерами), я привожу его к вам.Django admin: Разрешить ForeignKey базовому классу ссылаться на его подклассы

Ниже приводится классовая структура аналогична той, с которой я работаю:

# sources/models.py 
from django.db import models 

class Author(models.Model): 
    name = models.CharField(max_length=256) 
    slug = models.SlugField() 


class Source(models.Model): 
    author = models.ForeignKey(Author) 
    url = models.URLField(help_text='The URL where a copy of the source can be found.') 


class Book(Source): 
    title = models.CharField(max_length=256) 
    page = models.PositiveSmallIntegerField(help_text='Page where the source text appears.') 


class MagazineArticle(Source): 
    magazine_name = models.CharField(max_length=256) 
    issue_date = models.DateField() 
    title = models.CharField(max_length=256) 

И в отдельное приложение, я бы это:

# excerpts/models.py 
from django.db import models 
from sources.models import Source 

class Excerpt(models.Model): 
    excerpt = models.TextField() 
    source = models.ForeignKey(Source) 
    # Perhaps should be: 
    # source = models.OneToOneField(Source) 

Загвоздка в том, что в admin, я хочу иметь возможность создать либо Book, либо MagazineArticle в качестве источника для выдержки без отдельного поля в выдержке для каждого из них.

Один из способов, которым я читал об этом, может работать, это общие отношения, возможно, вместо этого используется абстрактный базовый класс, но я не нашел примеров, которые имеют смысл в моем контексте.

Каковы некоторые методы выполнения этого (желательно с примерами)?

ответ

0

Любой должен работать. Это, как вы могли бы сделать это с абстрактным базовым классом:

class Excerpt(models.Model): 
    excerpt = models.TextField() 
    source = models.ForeignKey(Source) 

    class Meta: 
     abstract = True 

class Book(Excerpt): 
    pass 
class Magazine(Excerpt): 
    pass 

Теперь вы можете сделать:

book = Book.objects.all() 
magazine = Magazine.objects.filter(source=1) 
+1

Я думаю, вы неправильно поняли мои модельные отношения. Книга не является выпиской, также не является статьей журнала. Это источники для выписки. И Excerpt не должен быть абстрактным классом. Во всяком случае, источник может быть абстрактным. – radicalbiscuit

+0

@radicalbiscuit не считают это истинным наследством. Подумайте о выдержке в качестве [mix-in] (http://stackoverflow.com/q/533631/1075247). – Pureferret

+0

@Pureferret действительно, я понимаю этот аспект, но это решение все еще не решает мою проблему (которую я не пересматривал за довольно долгое время). Эта структура ограничивала бы каждую «Книгу» или «Журнал» единственной выдержкой, где я ожидал, что сможет присвоить произвольное количество выдержек одному источнику. Мне нужно снова взглянуть на мою проблему. Это было давно, и у меня было больше практики, поэтому я мог бы разработать полезное решение, посвященное моим первоначальным проблемам. – radicalbiscuit

0

Ваш код уже правильный способ добиться того, что вы хотите. У вас есть наследование нескольких таблиц. У источника есть своя таблица, и все подклассы (Book, MagazineArticle) имеют свои собственные. Любые созданные книги или журналы автоматически создадут источник на стороне базы данных; а также ведет себя как «источник с дополнительными полями», когда вы ссылаетесь на модели подкласса. Также обратите внимание, что поля «один-к-одному» создаются из подкласса в базовый и базовый классы в подкласс. Вот как должен выглядеть администратор:

# admin.py 
# imports go here... 
source = Source() 
source.save() 
excerpt1 = Excerpt(source=source) 
book = Book() 
book.save() 
except2 = Excerpt(source=book.source) # source=book may also work; haven't checked... 
book2 = excerpt2.source.book 
if book is book2: 
    except2.save() # only save this if my code is correct... 
Смежные вопросы