** NOT NULL制約でのIntegrityErrorが失敗しました:learning_logs_topic.owner_id



Integrityerror Not Null Constraint Failed



最近、私は「Pythonの入門から実際の戦闘まで」の第19章を学んでいました。 Learning_logsモデルでは、トピックのユーザー属性が追加されました。つまり、ユーザーがログインした後に作成されたトピックです。このトピックの所有者属性は、ログインしたユーザーです。 .ForeignKey(User、on_delete = models.CASCADE)、ownerはUser(pthonバージョン3.7.4、djangoバージョン2.2.6)の外部キーであり、makemigrationsの後に次のプロンプトが表示されます。



このとき、「1)」のオプションを選択し、ユーザーID1のll_adminを選択します。このとき、元のトピックの元のユーザーIDは1、つまりll_adminです。 new_topicの実行中に次のエラーが発生しました。

/ new_topic / NOT NULL制約でのIntegrityErrorが失敗しました:learning_logs_topic.owner_id、エラーシーンは次のとおりです。



トピックモデルのソースコードは次のとおりです。

クラストピック(models.Model):
text = models.CharField(max_length = 200)
date_added = models.DateTimeField(auto_now_add = True)
owner = models.ForeignKey(User、on_delete = models.CASCADE)
def __str __(self):
self.textを返す



topicformのソースコードは次のとおりです。

クラスTopicForm(forms.ModelForm):
クラスメタ:
model =トピック
fields = ['text']
labels = {'text': ''}

Learning_logsフォルダーの下にあるviews.pyのnew_topicソースコードは次のとおりです。

def new_topic(request):
if request.method!= 'POST':
form = TopicForm()

そうしないと :
form = TopicForm(request.POST)
form.is_valid()の場合:
form.save()
HttpResponseRedirect(reverse( 'learning_logs:topics'))を返します

context = {'form':form}
render(request、 'learning_logs / new_topic.html'、context)を返します

このエラーは、null値制限エラーを示しています。owner、ownerは、モデルに新しく追加された属性です。所有者属性は既存のトピックに追加されますが、新しく追加されたトピックには所有者属性がないため、エラーが報告されます。

解決プロセスは次のとおりです。

(1)models.py属性にnull = Trueを追加して、この属性を空にできるようにします

変更後、owner = models.ForeignKey(User、on_delete = models.CASCADE、null = True)になり、変更後にエラーは表示されなくなりますが、新しく追加されたトピックの所有者はNULLであり、これは設計とは異なります。欲望

(2)models.pyにデフォルト値を追加します。

変更後、owner = models.ForeignKey(User、on_delete = models.CASCADE、default = 1)、変更後にエラーは表示されませんが、新しく追加されたトピックの所有者はID 1のユーザーであり、これはデザインが望む。

(3)TopicFormを変更し、所有者フィールドを追加します

変更後、TopicFormは次のようになります。

クラスTopicForm(forms.ModelForm):
クラスメタ:
model =トピック
fields = ['text、‘ owner ’']
labels = {'text': ''、 'owner': ''}

変更後、ユーザーはこの新しく作成されたトピックの所有者を次のように選択します。

現在ログインしているユーザーをこのトピックの所有者として選択できますが、ユーザーは現在ログインしていない他のユーザーを選択することもできるため、エラーのリスクが高まります。

(4)views.py new_topicビューで、request.userを使用して現在のユーザーを取得し、フォームに割り当てます。

つまり、if form.is_valid()の後に行を追加します。

form.instance.owner = request.user、変更後、次のようになります。

def new_topic(request):
if request.method!= 'POST':
form = TopicForm()

そうしないと :
form = TopicForm(request.POST)
form.is_valid()の場合:
form.instance.owner = request.user
form.save()
HttpResponseRedirect(reverse( 'learning_logs:topics'))を返します

context = {'form':form}
render(request、 'learning_logs / new_topic.html'、context)を返します

つまり、Formのinstanceパラメーターを使用して所有者属性を取得し、requset.userによって取得された現在のユーザーをこのインスタンスの所有者に割り当てます。変更されたプログラムは、所定の機能を実現します

(5)インスタンスパラメータも使用されますが、フォームが生成されると、変更されたnew_topicビューは次のようになります。

def new_topic(request):
if request.method!= 'POST':
form = TopicForm()

そうしないと :
form = TopicForm(request.POST)
topic = Topic()
topic.owner = request.user
form = TopicForm(request.POST、instance = topic)
form.is_valid()の場合:
form.save()
HttpResponseRedirect(reverse( 'learning_logs:topics'))を返します

context = {'form':form}
render(request、 'learning_logs / new_topic.html'、context)を返します

最初にトピックを生成し、次にそれを所有者に割り当て、次にこのトピックをインスタンスパラメータに割り当てると、スペースと時間のコストが高くなりますが、所定の機能も実現します。