Django: ログインしているユーザー名で記事を投稿する方法

# この記事の内容
記事やツイートを投稿するアプリで、投稿した記事の作成者をログインしているユーザー名にしたいときの設定方法について記載します。
DjangoでWebアプリを作り始めたのでその備忘です。

### 目次
1.失敗例
2.実装例


# 1.失敗例

記事投稿ができるアプリを作成する際に、「投稿した記事のauthorをログインユーザーに一致させ、ForeignKeyにより、authorと記事を1対多で対応させる」
ということを目指します。

まずは下記のようなクラスをmodels.py、forms.py、views.pyに作成しました。
しかしこれではうまくいきません。

```python:models.py

class Post(models.Model):
    content = models.TextField(max_length=50)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    date_posted = models.DateTimeField(default=timezone.now)
    likes = models.IntegerField(default=0)
    dislikes = models.IntegerField(default=0)

    def __str__(self):
        return self.content[:10]

```

```python:forms.py

class TweetPostForm(forms.Form):
    content = forms.CharField(label="tweet", max_length=50)

```

```python:views.py

class PostCreateView(CreateView):
    model = Post
    template_name = "tweet/post_create.html"
    fields = ['content']
    success_url = reverse_lazy('index')
```

上記で実行すると下記のようなエラーが生じます。

```
django.db.utils.IntegrityError: NOT NULL constraint failed: tweet_post.author_id
```


# 2.実装例
解決方法が公式ドキュメントのここに書いてありました。
(https://docs.djangoproject.com/en/3.0/topics/class-based-views/generic-editing/#models-and-request-user)

> Models and request.user
To track the user that created an object using a CreateView, you can use a custom ModelForm to do this. First, add the foreign key relation to the model:

```python:models.py
from django.contrib.auth.models import User
from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=200)
    created_by = models.ForeignKey(User, on_delete=models.CASCADE)

    # ...
```
> In the view, ensure that you don’t include created_by in the list of fields to edit, and override form_valid() to add the user:

```python:views.py

from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.edit import CreateView
from myapp.models import Author

class AuthorCreate(LoginRequiredMixin, CreateView):
    model = Author
    fields = ['name']

    def form_valid(self, form):
        form.instance.created_by = self.request.user
        return super().form_valid(form)
```

> LoginRequiredMixin prevents users who aren’t logged in from accessing the form. If you omit that, you’ll need to handle unauthorized users in form_valid().


ということで上記のドキュメントに従い下記のように書き換えるとうまくいきました。

```python:models.py

class Post(models.Model):
    content = models.TextField(max_length=50)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    date_posted = models.DateTimeField(default=timezone.now)
    likes = models.IntegerField(default=0)
    dislikes = models.IntegerField(default=0)

    def __str__(self):
        return self.content[:10]

```

```python:forms.py

class TweetPostForm(forms.Form):
    content = forms.CharField(label="tweet", max_length=50)

```

```python:views.py

class PostCreateView(LoginRequiredMixin, CreateView):
    model = Post
    template_name = "tweet/post_create.html"
    fields = ['content']
    success_url = reverse_lazy('tweet:index')

    def form_valid(self, form):
        form.instance.author = self.request.user
        return super().form_valid(form)
```