2011-10-25 10 views
15

私はDjangoを使って個人的なプロジェクトを構築しています(私はDjangoが好きなので、スキルは不足しています)。私は基本的な要件を持っています、私はPythonを知っています、私は注意深くDjangoの本を3回ではなく2回読んでいます。抽象クラスへの外部キー(一般的な関係)

私の目標は、DjangoベースのWebインターフェイスを使用して簡単な監視サービスを作成して、自分の「ノード」(サーバー)の状態を確認できるようにすることです。各ノードには複数の「サービス」があります。アプリケーションは、各ノードの各サービスの可用性をチェックします。

私の問題は、私のデータベースにさまざまな種類のサービスをどのように表現するか分かりません。 「サービス種別」フィールドで、

  • 単一サービスモデル、およびフィールドを持つ大きな混乱:私は2つの「解決策」を考えました。 (私はデータベースモデリングに大きな経験はありませんが、これは... "悪い"と思われます)
  • サービスモデル。私はこの解決策が好きですが、どのように私がこれらを参照することができないのかわかりません。DIFFERENTサービスが同じフィールドにあります。

これは私のmodels.pyファイルからの短い抜粋です:もちろん(私はこの問題に関連していないすべてのものを削除)

from django.db import models 

# Create your models here.                               
class service(models.Model): 
    port = models.PositiveIntegerField() 
    class Meta: 
     abstract = True 

class sshService(service): 
    username = models.CharField(max_length=64) 
    pkey = models.TextField() 

class telnetService(service): 
    username = models.CharField(max_length=64) 
    password = models.CharField(max_length=64) 

class genericTcpService(service): 
    pass 

class genericUdpService(service): 
    pass 

class node(models.Model): 
    name = models.CharField(max_length=64) 
    # various fields                                 
    services = models.ManyToManyField(service) 

、のManyToManyFieldを持つ行が偽です。私は "*サービス"の代わりに何を置くべきか分かりません。私は正直にこれについての解決策を探しました、私は "一般的な関係"、トリプルジョインテーブルを聞いたが、私は本当にこれらのことを理解していない。

また、英語は私の母国語ではないので、データベース構造とセマンティクス、私が読んだの私の知識と理解に来るが限定されている(しかし、それは私の問題だ)

答えて

13

まず、現在持っている抽象モデルではなく、Djangoのmulti-table inheritanceを使用してください。

あなたのコードは、その後になる:

データベースレベルで
from django.db import models 

class Service(models.Model): 
    port = models.PositiveIntegerField() 

class SSHService(Service): 
    username = models.CharField(max_length=64) 
    pkey = models.TextField() 

class TelnetService(Service): 
    username = models.CharField(max_length=64) 
    password = models.CharField(max_length=64) 

class GenericTcpService(Service): 
    pass 

class GenericUDPService(Service): 
    pass 

class Node(models.Model): 
    name = models.CharField(max_length=64) 
    # various fields                                 
    services = models.ManyToManyField(Service) 

、これは、行がそれらのそれぞれの子のサービスごとに1つのテーブルと1対1の関係を介して連結される「サービス」テーブルを作成します。 。

このアプローチの唯一の難点は、次のような何かをするときということです:

node = Node.objects.get(pk=node_id) 

for service in node.services.all(): 
    # Do something with the service 

「サービス」は、ループ内のあなたのアクセスは、親タイプのものであろうオブジェクト。 あなたはこれらを事前に持っています入力し何の子供を知っている場合は、あなただけの、次のように子クラスにアクセスすることができます。

from django.core.exceptions import ObjectDoesNotExist 

try: 
    telnet_service = service.telnetservice 
except (AttributeError, ObjectDoesNotExist): 
    # You chose the wrong child type! 
    telnet_service = None 

あなたが事前に子タイプがわからない場合、それは少しトリッキー取得します。親モデルの 'serviceType'フィールドを含むいくつかのハッピー/乱雑な解決策がありますが、Joe Jが言及したように、より良い方法は 'サブクラス化クエリセット'を使用することです。 django-model-utilsのInheritanceManagerクラスがおそらく最も使いやすいでしょう。それのドキュメントhereを読んで、それは本当に素晴らしいコードです。

+0

詳細、コード、答えの完全なありがとう。 @Joe Jの1つでは、私のアプリケーションのモデリングを通して私が助けてくれると確信しています。このサイトは素晴らしいですが、そのユーザーもあります。 – pistache

+0

これはあなたがここで与えたすばらしい解決策です。特にInheritanceManagerのトリックと、django-model-utilsパッケージ全体です。再度、感謝します – pistache

6

私はあなたが考えるかもしれません一つのアプローチがあると思います「サブクラス化クエリーセット」。基本的には、親モデルにクエリを実行できるようになり、結果クエリセット内の子モデルのインスタンスが返されます。 、

[ <sshServiceInstance>, <telnetServiceInstance>, <telnetServiceInstance>, ...] 

これを行う方法のいくつかの例についてはブログの記事のリンクをチェックアウト:

models.service.objects.all() 

、それはあなたに次のような結果を返すがあります。それはあなたのようなクエリをやらせるだろうリンク先あなたがこのアプローチを使用する場合を例にそうであるように

http://jazstudios.blogspot.com/2009/10/django-model-inheritance-with.html

しかし、あなたは抽象として、あなたのサービスモデルを宣言するべきではありません。確かに、余分な結合を導入する予定ですが、全体的に私はサブクラスのクエリセットがクエリセット内のオブジェクトの混合セットを返すためにかなりうまく動作することを発見しました。とにかく

、あなたは一般的な外部キーの関係を探しているなら、あなたが(ジャンゴに組み込まれている)Django contenttypes frameworkをチェックする必要があります ジョー

+1

本当にありがとうございます。あなたの答えは@Voightkampffの1つでモデルの継承を理解するのに役立ち、私のモデルデータ構造を考える新しい方法を私に与えました。面ではなく、これはstackoverflow.comの私の最初の質問でした、そして、私は本当にウェブサイト、インターフェイス、ユーザー、答えに満足しています、私は今も私の知識を共有してうれしいです。 :) – pistache

0

、このことができます願っています。ドキュメントでは、その使い方や一般的な関係の使い方を説明しています。

+1

ありがとうございましたが、私が言ったように、私はすでにそれをチェックしましたが、私は実際に理解していないし、インターネットの例を私のユースケースにマップすることもできませんでした。 – pistache

0

実際のサービスは1つのノードにしかできません。その場合、フィールドがない場合

node = models.ForeignKey('node', related_name='services') 

serviceクラスのクラス?

関連する問題