Сохранить данные из ChoiceField в базу данных Django

Я новичок в Django и я создал Форму, которая показывает одно поле для выбора. Данные в поле вычисляются на ходу формой.

Теперь мне нужно, чтобы после отправки данных, они сохранялись в базе данных. Единственная проблема заключается в том, что по какой-то причине я получил IntegrityError error NOT NULL constraint failed: manager_playlist.user_id

Ниже мои представление, форма и модель в Django

views.py

def playlist(request):
    if not is_user_already_auth_spotify(request):
        messages.error(request, "You're not authenticated with Spotify, please authenticate here")
        return redirect('/members/account/' + request.user.username)

    if request.method == "POST":
        form = ChoosePlaylistForm(request.POST, request=request)
        if form.is_valid():
            form.save()
            messages.success(request, "Playlist successfully chosen")
            return HttpResponseRedirect('account')
        else:
            pass
    else:
        form = ChoosePlaylistForm(request=request)

    return render(request, 'show_playlist.html', {"playlist_choose_form": form})

forms.py

class ChoosePlaylistForm(ModelForm):

    playlists = forms.ChoiceField(choices=())

    class Meta:
        model = Playlist
        fields = ('playlists',)

    def __init__(self, *args, request=None, **kwargs):
        super(ChoosePlaylistForm, self).__init__(*args, **kwargs)
        self.request = request
        self.fields['playlists'].choices = self.generate_selection()

    def generate_selection(self):
        sp_auth, cache_handler = spotify_oauth2(self.request)
        spotify = spotipy.Spotify(oauth_manager=sp_auth)
        s_user = spotify.current_user()
        u_playlists = spotify.user_playlists(s_user['id'], limit=10)

        choices = []
        for playlist in u_playlists["items"]:
            if playlist["owner"]["id"] == s_user['id']:
                playlist_choice = (playlist["id"], playlist["name"])
                choices.append(playlist_choice)
            else:
                pass

        return choices

model.py

class Playlist(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    playlists = models.CharField(max_length=50, null=True, blank=True)  # playlists are the ids of the playlists

    def __str__(self):
        return self.playlists

Причина ошибки заключается в том, что при создании нового объекта Playlist поле user не должно быть пустым (вы не добавили null=True, и, конечно, в этом не было бы смысла, если бы вы это сделали). Теперь форма проверяется, потому что форма не требует поля user, а только поле playlists. У вас есть несколько вариантов.

Вариант 1
. Добавьте обязательное поле в вашу форму (я не тестировал это, пожалуйста, проверьте docs!):

class ChoosePlaylistForm(ModelForm):

    playlists = forms.ChoiceField(choices=())

    class Meta:
        model = Playlist
        fields = ('playlists', 'user',)   # NOTE THE CHANGE HERE

    def __init__(self, *args, request=None, **kwargs):
        super(ChoosePlaylistForm, self).__init__(*args, **kwargs)
        self.request = request
        self.user = request.user    # Add the user to the form

Вариант 2
. Сохраните форму как есть, используя commit=False, затем добавьте недостающее поле перед сохранением модели:

if request.method == "POST":
        form = ChoosePlaylistForm(request.POST, request=request)
        if form.is_valid():
            playlist = form.save(commit=False)    # NOTE THE CHANGE HERE
            playlist.user = request.user          # Add the user to the partial playlist
            playlist.save()                       # Now you can save the playlist
            
            messages.success(request, "Playlist successfully chosen")
            return HttpResponseRedirect('account')

Вариант 3
. Добавьте поле при создании самой формы (я не уверен, что мой синтаксис здесь правильный):

form = ChoosePlaylistForm(request.POST, request=request, instance=request.user)
Вернуться на верх