2015-03-13 96 views
0

我試圖對學習資源(書籍,DVD等)進行建模,以及這些資源具有哪些先決條件。通過Django中的關係訪問完整對象

先決條件也是一種資源。所以我的問題是,什麼Django 建模技術最好地捕捉這種關係?這項研究的資源是 簡單:

from django.db import models 
from django.utils import timezone 

class Resource(models.Model): 
    title = models.CharField(max_length=300) 
    shortcode = models.CharField(max_length=20, null=True, blank=True) 
    img = models.URLField(null=True, blank=True) 
    summary = models.TextField(null=True, blank=True) 
    url = models.URLField('Link to Resource', null=True, blank=True) 
    pub_date = models.DateTimeField('date published') 

    def was_published_recently(self): 
     return self.pub_date >= timezone.now() - datetime.timedelta(days=1) 

    def __unicode__(self): 
     return self.title 

但是,我不知道什麼是「最好」的方式向 前提下,給定的模型,它是一個Resource也是最重要的是有可變數量的先決條件(從而消除了簡單地擁有自我指涉的父母的可能性)。這是我目前的做法:

class Prereq(models.Model): 
    prereq = models.ForeignKey(Resource, null=True, related_name='prereq_backlink') 
    resource = models.ForeignKey(Resource, null=True, related_name='prereq_resource') 

    def __unicode__(self): 
     return self.resource.title 

這種方法的問題是訪問的先決條件並 沒有給我一個完整的資源對象的工作,所以我不能訪問 的各個領域(標題,簡碼,等):

[email protected]:~/domains/org/metaperl/tmp/idhhb/django/mysite$ ./manage.py shell 
>>> from idhhb.models import Resource, Prereq 
from idhhb.models import Resource, Prereq 
>>> p = Resource.objects.get(id=2) 
>>> p.title 
u'American Book of the Dead' 
>>> r = Resource.objects.get(id=2) 
r = Resource.objects.get(id=2) 
>>> p1 = r.prereq_backlink 
>>> p2 = r.prereq_resource 
>>> p1 
<django.db.models.fields.related.RelatedManager object at 0x2e279d0> 
>>> p2 
<django.db.models.fields.related.RelatedManager object at 0x2e27a90> 
>>> p1.title 
p1.title 
Traceback (most recent call last): 
    File "<console>", line 1, in <module> 
AttributeError: 'RelatedManager' object has no attribute 'title' 

>>> p2.title 
p2.title 
Traceback (most recent call last): 
    File "<console>", line 1, in <module> 
AttributeError: 'RelatedManager' object has no attribute 'title' 
>>> 
+2

爲什麼不直接使用一個自我指涉的關係?如果某個資源具有「父」fk,那麼這是您的先決條件 – Brandon 2015-03-13 18:42:12

+0

因爲先決條件的數量是可變的,理想情況下限制爲5,但該要求可以放寬。但是,肯定不是隻有一個先決條件。 – 2015-03-13 21:42:35

+2

好吧,爲什麼不能自我參照多對多的關係呢? – 2015-03-13 21:48:09

回答

0

prereq_backlinkprereq_resource是經理這樣進入Resource看起來像:

r = Resource.objects.get(id=2) 
for prereq in r.prereq_backlink.all(): 
    print prereq.resource.title 

但我加入@ daniel-roseman的問題:爲什麼你沒有使用ManyToManyField來完成這項任務?

class Resource(models.Model): 
    ... 
    prereqs = models.ManyToManyField('self') 
+0

但不是'prereq.resource.title'給你的id = 2的資源標題,而不是先決條件資源的標題? – 2015-03-13 22:47:41

+0

我試圖使用'ManyToManyField',但它並沒有出現在我自己的引用中。我現在將研究自我指涉的方面。 – 2015-03-13 22:49:50

+0

不,'prereq_backlink'關係與'prereq'字段相關聯,因此它是'prereq.prereq.title'會給你id = 2的原始資源。 – catavaran 2015-03-13 23:00:45

1

感謝this blog post我能實現這個使用ManyToManyField的建議。我必須說這篇博文比我在Django網站上找到的任何文檔都要好。

MODEL:

class Resource(models.Model): 
    title = models.CharField(max_length=300) 
    shortcode = models.CharField(max_length=20, null=True, blank=True) 
    img = models.URLField(null=True, blank=True) 
    summary = models.TextField(null=True, blank=True) 
    url = models.URLField('Link to Resource', null=True, blank=True) 
    pub_date = models.DateTimeField('date published') 
    prereqs = models.ManyToManyField(
     'self', through='Prereq', symmetrical=False, related_name='prerequired') 

    def was_published_recently(self): 
     return self.pub_date >= timezone.now() - datetime.timedelta(days=1) 

    def __unicode__(self): 
     return self.title 

class Prereq(models.Model): 
    resource = models.ForeignKey(Resource, null=True, related_name='main_resource') 
    prereq = models.ForeignKey(Resource, null=True, related_name='prereq_resource') 

ADMIN:

from django.contrib import admin 
from idhhb.models import Resource, Prereq 

class PrereqInline(admin.TabularInline): 
    model = Prereq 
    fk_name = 'resource' 
    extra = 5 

class ResourceAdmin(admin.ModelAdmin): 
    fieldsets = [ 
     (None, {'fields': 'title shortcode img summary url pub_date'.split() }), 
    ] 
    inlines = [PrereqInline,] 


admin.site.register(Resource, ResourceAdmin) 

模板:

{% for prereq in resource.prereqs.all %} 
    <li>{{ prereq.id }}</li> 
{% endfor %} 
+0

太棒了。很高興你按照你想要的方式工作。 – Brandon 2015-03-14 00:38:17