開発していた予定定期報知アプリが完成したので、djangoとpythonanywhereで躓いた細々としたことのまとめ

開発していたアプリが完成したので、djangoで躓いた細々としたことをまとめていきます。詳しい理由はわからないことがほとんどなので、質問にはおそらく答えられないことが多いです。参考にしたurlをそれぞれつけておくのでそちらをご覧ください。


以下からdjangoで躓いた細々としたことのまとめです。

開発はローカルでやる人が多いでしょうが、そのときlocal_setting.pyを作るとデバッグに便利です。ただし、セキュリティ関連の設定はlocal_setting.pyで明確に打ち消さないと面倒なことが起こります。たとえばhttpsを強制する設定があるのですが、それをローカルで適用してしまうとアクセスできなくなり、キャッシュなどを消す必要が出てきます。
https://qiita.com/jp_ibis/items/0ac1ba8aba1398f2a492
もしくは以下のように完全に分けるのもいいでしょう。
https://qiita.com/okoppe8/items/e60d35f55188c0ab9ecc

#axesとかrulesも使う場合

```
login(request, user)

axesとかrulesも使う場合
login(request, user,backend='django.contrib.auth.backends.ModelBackend')
```
このときloginにはbackend='django.contrib.auth.backends.ModelBackend'を渡さないと、
multiple authentication backends configured and therefore must provide the `backend` argument or set the `backend` attribute on the user
が発生します。AUTHENTICATION_BACKENDSに問題が無いときはこれを確認してみてください。

https://stackoverflow.com/questions/45961459/multiple-authentication-backends-configured-and-therefore-must-provide-the-back

#formsetにkwargsをわたす
```
#古いやり方
modelformset_factory(FirmPartner, form=FirmPartnerForm, can_delete=True, extra=1,
                     form_kwargs={'request': request, 'application': application})

#2020年
ConceptFormSet = modelformset_factory(
    model = Concept,
    form = ConceptForm,
    fields = show_fields
)
#分けて書く
formset = ConceptFormSet(form_kwargs={'action': 'detail'})
```
書き方に新旧があるようです。現在は下の書き方を使います。

https://stackoverflow.com/questions/39345346/can-we-send-a-request-object-or-keyword-argument-to-modelformset-factory-in-djan

https://stackoverflow.com/questions/59827348/how-to-pass-extra-kwargs-to-form-in-django-modelformset-factory

https://stackoverflow.com/questions/38560344/how-to-use-the-new-form-kwargs-on-an-inline-formset

#json_scriptフィルタ

```
view
def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context.update({
            "update":"update"
        })

html
{{ update |json_script:"update-data" }}

document.getElementById('update-data').innerText=='"update"'
true

document.getElementById('update-data').innerText=="update"
false

```
viewからjson_scriptで値を渡すとき、上のようにしないと正誤判定ができませんでした。
真偽値は"true"でだけで大丈夫です。

#raise ValidationError
こういうのを追加するとき、object has no attribute 'object'が起こるときがあります。
もしそれがget_context_dataでなら、以下が必要です。

```

def post(self, request, *args, **kwargs):
        #ValidationErrorのため
        self.object = self.get_object()
```

https://stackoverflow.com/questions/34460708/checkoutview-object-has-no-attribute-object

#idやpkを伴うリンク

```    
<a class="box" href="{% url 'app:form_detail' form.id %}">detail</a>    
<a class="box" href="{% url 'app:form_detail' form.id.value %}">detail</a>
<a class="box" href="{% url 'app:form_detail' 1 %}">idが1のdetail</a>
```
上のような感じで書いてあるページは多いのですが、value をつけないと、NoReverseMatch がおきる場合があります。一度idをadminでしらべて、上の三番目のように直接form.idの位置に書いても動きはするので、エラーの原因が分からなかったら試してみたり、アドレスバーに直接入力してみるのもいいかもしれません。

#updateviewでのidやpk

```
app_form = AppForm(request.POST)
if app_form.is_valid():
　　　　form = app_form.save(commit=False)
　　　　form.pk = self.kwargs['pk']
```
こういう書き方をするときに最後のを忘れると新規作成になってしまう。

#inputをtextareaに

metaに追加する。keyは変更したいフィールド名。ただしレイアウト的にはcolsは指定しないか、widthを使ったほうがいいです。

```
from django.forms import ModelForm, Textarea

class PostModelForm(ModelForm):
    class Meta:
        model = Post
        widgets = {
            'content': Textarea(attrs={'cols': 80, 'rows': 20}),
        }
```
https://stackoverflow.com/questions/8761106/how-can-i-get-a-textarea-from-modelmodelform

#datetime.datetimeとdatetime.date

```
date=datetime.datetime.strptime("2000-02-02", '%Y-%m-%d')
#これで作られるのはdatetime.datetime datetime.dateがほしいときは
date=datetime.datetime.strptime("2000-02-02", '%Y-%m-%d').date()
```

この二つは一見同じように見えるときがありますが別物なので、開発中日付がどうしても==にならないときはtyoe()などで確認してみてください。



#cssでtransformとanimationを併用するとき

```
@keyframes slideIn {
  0%, 100% {
    transform: translate(10px) rotate(0deg);
    color: red;
  }
  25% {
    transform: translate(125px) rotate(360deg);
    color: green;
  }
}
```
transformを併用するときはkeyframes にまとめて書きます。

https://stackoverflow.com/questions/36455370/css-animation-rotate-and-translate-doesnt-work-together

#pythonanywhereのScheduled Task

```
from django.core.management.base import BaseCommand

class Command(BaseCommand):
    def handle(self, *args, **options):
        command...

```
どんなbashの命令でも実行できそうですが、djangoを利用する場合はpython manage.py Command_file_name　にしたほうが無難です。そうでないと例えばDJANGO_SETTINGS_MODULEかsettings.configure()してほしいというエラーがでます。
https://qiita.com/checkpoint/items/b6947501774b4008e077
https://help.pythonanywhere.com/pages/environment-variables-for-web-apps/
https://stackoverflow.com/questions/7598793/setting-django-settings-module-under-virtualenv
また、仮想環境を使用している場合は

```
ファイルパスに

/home/myusername/myproject/mytask.py

こうではなく

/home/myusername/.virtualenvs/myvenv/bin/python /home/myusername/myproject/mytask.py

と入力する。

```

https://help.pythonanywhere.com/pages/VirtualEnvInScheduledTasks/

#pythonanywhereのtaskでmodelを使う場合

modelにはapp名のlabelをつける必要があります。ないと
doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.

```
class TopicsTr(models.Model):

   class Meta:
      abstract = True  # specify this model as an Abstract Model    
      app_label = 'blogs'
```

https://fclout.hateblo.jp/entry/2020/06/30/%E3%80%90%E8%A7%A3%E6%B1%BA%E3%80%91sphinx-build%E6%99%82%E3%81%AB%E3%80%8Cdoesn%27t_declare_an_explicit_app_label_and_isn%27t_in_an_application_in_INSTALLED_APPS_%E3%80%8D%E3%81%A8%E8%A8%80%E3%82%8F

https://www.pythonanywhere.com/forums/topic/13787/