(これは古い質問ですが、それでも人々をつまずかせ、既存の正規化されたスキーマでDjangoを使用している人との関連性が高い領域です。)
管理されていないモデルであっても、Djangoは数値の「id」を想定しているため、SELECTステートメントで数値の「id」を追加する必要があります。行のどこかに一意の整数値が保証されていない場合は、row_number()ウィンドウ関数を使用してこれを実行できます(ビューでは、これがよくある場合です)。
この場合、私はウィンドウ関数でORDER BY句を使用していますが、有効なことは何でもできます。その間、何らかの形で役立つ句を使用することもできます。リレーションへのDjangoORMドット参照はデフォルトで「id」列を検索し、偽物であるため、使用しないように注意してください。
さらに、オブジェクト内で出力列を使用する場合は、出力列の名前をより意味のある名前に変更することを検討します。これらの変更を行うと、クエリは次のようになります(もちろん、「AS」句の代わりに独自の用語を使用してください)。
CREATE VIEW qry_desc_char as
SELECT
row_number() OVER (ORDER BY tbl_char.cid) AS id,
tbl_desc.iid_id AS iid_id,
tbl_desc.cid_id AS cid_id,
tbl_desc.cs AS a_better_name,
tbl_char.cid AS something_descriptive,
tbl_char.charname AS name
FROM tbl_desc,tbl_char
WHERE tbl_desc.cid_id = tbl_char.cid;
それが完了すると、Djangoではモデルは次のようになります。
class QryDescChar(models.Model):
iid_id = models.ForeignKey('WhateverIidIs', related_name='+',
db_column='iid_id', on_delete=models.DO_NOTHING)
cid_id = models.ForeignKey('WhateverCidIs', related_name='+',
db_column='cid_id', on_delete=models.DO_NOTHING)
a_better_name = models.CharField(max_length=10)
something_descriptive = models.IntegerField()
name = models.CharField(max_length=50)
class Meta:
managed = False
db_table = 'qry_desc_char'
上記のように「db_column」引数を使用して、Djangoモデルの列名をより説明的なもので宣言できるため、id列名の最後に「_id」の部分は必要ありません(ただし、ここではそれだけです) Djangoが別のものを追加するのを防ぐためcid_idとiid_idの末尾に「_id」があります。これにより、コードにゼロのセマンティック値が追加されます)。また、「on_delete」引数にも注意してください。Djangoは、カスケード削除に関しては独自のことを行います。興味深いデータモデルでは、これは望ましくありません。ビューに関しては、エラーが発生し、トランザクションが中止されます。Django 1.5より前では、DO_NOTHINGが実際に「何もしない」ことを意味するようにパッチを適用する必要があります。そうしないと、削除サイクルを実行する前に、関連するすべてのオブジェクトを(不必要に)クエリして収集しようとし、クエリが失敗して停止します。操作全体。
ちなみに、先日、これを行う方法について詳しく説明しました 。