Django 備忘録

業務中・勉強中に覚えたDjangoのこれどう書くんだったっけとよく思うものを残します。
基本的にクラスビューな書き方です。
知見を得た順に書くので多分まとまった書き方はではないのでご注意を。
随時更新していきます。

modelを取り扱いますが共通して以下のmodelを使います。
[Djangoのチュートリアル](https://docs.djangoproject.com/ja/3.1/intro/overview/)を参考にしています。


```models.py
from django.db import models

class Reporter(models.Model):
    full_name = models.CharField(max_length=70)

class Article(models.Model):
    pub_date = models.DateField()
    headline = models.CharField(max_length=200)
    content = models.TextField()
    reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
```



# post等でurls.pyのpkを取得する
```django.py
urlpatterns = [
...
path('url/detail/<int:pk>/', views.Detail.as_view(), name='detail'),
...
]
```
記事のアップデート等をしたあと、詳細画面へ遷移させたい時に`<int:pk>`が必要になる。
これをviews.pyのpostで取得する場合以下のようにする。


```views.py
class Update(UpdateView):
    ...
    def post(self, request, **kwargs):
        print(self.kwargs["pk"]) # ←このような形で取得可能

        # 詳細画面へ遷移させる
        return redirect('detail', pk=self.kwargs["pk"])
```

postに限らず、get, get_context_dataでも大体これで取れる。


# META情報を取得する

```views.py
class Template(TemplateView):
    ....
    def get(self, request, *args, **kwargs):
        print(request.META)  
    ....
```

辞書型なのでHTTP_REFERE等を確認したい場合は`request.META["HTTP_REFERER"]`のように書く


# キャッシュを残さない
```views.py
class Template(TemplateView):
    ....
    @method_decorator(never_cache)
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

```

ページアクセスした際キャッシュが残りますが、そのキャッシュを残したくない場合
`@method_decorator(never_cache)`を使えばキャッシュを残さない。
template内でajaxなど動的な処理を行ったときによく使います。


# modelをDataFrame形式で取得する

```python.py
df = pd.DataFrame.from_records(
    Article.objects.all().values_list("pub_date", "headline", "content"),
    columns=["pub_date", "headline", "content"]
)
```

DjangoというよりPandasよりの知識
Pandasで取得すればデータの加工などが楽になりますが、
modelのデータをpandasのDataFrameとして取得する方法です。

# ChoiceFieldを継承したoptionタグに特殊な操作を行いたい場合

forms.pyでselectタグのoptionタグに特定のdata属性を持たせたい場合の話です。

以下のようにforms.pyを定義した場合、

```forms.py
from django import forms
from .models import Article, Reporter

class ArticleForm(forms.ModelForm):
    reporter = forms.ModelChoiceField(queryset=Reporter.objects.all())

    class Meta:
        model = Article
        fields = ['headline', 'content', 'reporter']

```

reporterフィールドはtemplate側に以下のように表示される。

```template.html 
<!-- レンダリング後 -->
<select id='id_reporter' name='reporter'>
    <option value="1">レポーター1</option>
    <option value="2">レポーター2</option>
    <option value="3">レポーター3</option>
</select>
```

このreporterフィールドを以下のようにしたい。
data-src属性にtextの値を平仮名に変換した情報を持たせたい。

```template.html
<select id='id_reporter' name='reporter'>
    <option value="1" data-src="れぽーたー1">レポーター1</option>
    <option value="2" data-src="れぽーたー2">レポーター2</option>
    <option value="3" data-src="れぽーたー3">レポーター3</option>
</select>
```


forms.pyを以下のように修正する

```forms.py
import jaconv
from django import forms
from .models import Article, Reporter

class ReporterSelect(forms.Select):
    def create_option(self, name, value, label, selected, index, subindex=None, attrs=None):
        option = super().create_option(name, value, label, selected, index, subindex, attrs)
        if label:
            option['attrs']['data-src'] = jaconv.kata2hira(label)
        return option

class ArticleForm(forms.ModelForm):
    reporter = forms.ModelChoiceField(
        queryset=Reporter.objects.all(),
        widget=ReporterSelect
    )

    class Meta:
        model = Article
        fields = ['headline', 'content', 'reporter']

```