Djangoが他のPolymorphicと挙動が異なる件

## Polymorphism
プログラミングには**Polymorphism**という考え方があり、Wkipediaには以下のように掲載されています。[リンク](https://ja.wikipedia.org/wiki/%E3%83%9D%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%95%E3%82%A3%E3%82%BA%E3%83%A0)
> ポリモーフィズム（英: Polymorphism）とは、プログラミング言語の型システムの性質を表すもので、プログラミング言語の各要素（定数、変数、式、オブジェクト、関数、メソッドなど）についてそれらが複数の型に属することを許すという性質を指す。

同様に、本来RDBでは一つのカラムは一つのテーブルに対してしかリレーションを持てないところを、複数のテーブル対してリレーションを持つ(複数の型に属する)ようなテーブルのことをPlymorphic Modelと言います。

## SQLアンチパターンで紹介されているポリモーフィック関連

[SQLアンチパターン](https://www.oreilly.co.jp/books/9784873115894/)という本をご存知でしょうか？RDBの設計やクエリのアンチパターンとその解決方法を紹介解説してくれています。
その中でポリモーフィック関連についても解説があったのでサンプルとして紹介します。


![asdfasdf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235240/caf9426b-ebb3-6f72-ec8c-22e1ad30f637.png)


概要を解説するとBugs(バグ起票)テーブル、FeatureRequests(機能要望)テーブルがあり、それぞれにComments(コメント)をつけることができる。
Commentsのissue_idはBugsのbug_id、FeatureRequestsのrequesst_idが格納され、どちらのテーブルを紐付ているか判断するためにissue_typeに'Bugs'か'FeatureRequests'を格納する。

このとき実際に発行されるSQLやDBの外部キーが使えないことが、バグ等の原因になると言及されています。

## Django Polymorphicの奇妙な動き
**django-polymorphic**と**Rails ActiveRecord**を比較して挙動の差を確認できます。
チュートリアルに従ってそれぞれを実装すると以下のようになります。

### Rails
modelファイル

```ruby
class Comment < ApplicationRecord
  belongs_to :commentable, polymorphic: true
  belongs_to :
end
 
class Bug < ApplicationRecord
  has_many :comments, as: :commentable
end
 
class FeatureRequest < ApplicationRecord
  has_many :comments, as: :commentable
end
```

migrationファイル

```ruby
class CreateComments < ActiveRecord::Migration[5.0]
  def change
    create_table :comments do |t|
      t.string  :comment
      t.references :commentable, polymorphic: true
      t.timestamps
    end
  end
end
```

CraeteとRead

```ruby
# Create
Bug.create(title: "bug", description: "hello")
FeatureRequest.create(title: "feature request", description: "hello")
Comment.create(comment: 'comment on Bug', commentable_type: 'Bug', commentable_id: 1)
Comment.create(comment: 'comment on FeatureRequest', commentable_type: 'FeatureRequest', commentable_id: 1)

# Read
Bug.first.comments.first
#<Comment id: 1, comment: "comment on Bug", commentable_type: "Bug", commentable_id: 1, created_at: "2019-09-22 15:55:44", updated_at: "2019-09-22 15:55:44">

FeatureRequest.first.comments.first
#<Comment id: 1, comment: "comment on FeatureRequest", commentable_type: "FeatureRequest", commentable_id: 1, created_at: "2019-09-22 15:55:44", updated_at: "2019-09-22 15:55:44">
```

### Django

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

class Comment(PolymorphicModel):
    id = models.BigAutoField(primary_key=True)
    comment = models.TextField()

class Bug(Comment):
    title = models.TextField()
    description = models.TextField()

class FeatureRequest(Comment):
    title = models.TextField()
    description = models.TextField()
```

CreateとRead

```python
# Create
Bug(comment='Bug', title="Bug title", description="Bug description").save()
FeatureRequest(comment='FeatureRequest', title="FeatureRequest title", description="FeatureRequest description").save()

# Read
Comment.objects.first()
# <Bug: Bug object (1)>
```
### 解説
Rails方はまさしくSQLアンチパターンの例のTableが生成されました。
SQLアンチパターンでも取り上げられているように、CommentとBug、CommentとFeatureRequestはそれぞれ外部結合してませんが、ActiveRecordによってそれを意識しなくてもいいようになっています。
それに対してDjangoのPolymorphicModelの挙動は全く異なります。
生成されるDBをERに起こすと以下のようになります。

![aass.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235240/bc801de8-368b-d53c-301d-74d601300bfd.png)

Bugs、FeatureRequestはともにcomment_ptr_idでCommentsと結合しています。
これはBugs、FeatureRequestが共通の属性Commentsを継承(inherit)しているようです。
さらに一対一の関係になっているため、もともとやりたことはもやはできません。

## 感想
DjangoのPolymorphicModelはSQLアンチパターンで取り上げられているいわゆるポリモーフィック関連とは全く異なるということがわかりました。
もはやPolymorphicModelとポリモーフィック関連は別のものを指している？とさえ感じるレベルです。