Я пытаюсь создать приложение для отслеживания игр, и я хотел, чтобы пользователь мог видеть, а затем обновлять, если захочет, форму, которая включает и выключает функции для отслеживания. Я знаю, что это должно быть довольно просто, но я не могу хоть убей заставить форму заполниться данными пользователя, а затем иметь возможность ее обновить. Заранее спасибо.
view.py
@login_required(login_url='my-login')
def track_pref(request):
user = User.objects.get(username=request.user)
print(user)
if request.method == "POST":
print('first if')
form = UpdateTrackPrefForm(request.user, request.POST)
if form.is_valid():
print('Form Valid')
obj = form.save(commit=False)
obj.user = user
obj.save()
return HttpResponseRedirect('/view-games')
else:
print("else statement")
form = UpdateTrackPrefForm()
context = {'form': form, 'user': user, }
return render(request, 'gametracker_app/track-preference.html', context=context)
формы.py
class UpdateTrackPrefForm(forms.ModelForm):
track_cedh = forms.BooleanField(required=False)
track_wincon = forms.BooleanField(required=False)
track_tournament = forms.BooleanField(required=False)
track_medium = forms.BooleanField(required=False)
class Meta:
model = TrackPref
fields = {'track_cedh',
'track_wincon',
'track_tournament',
'track_medium', }
модели.py
class TrackPref(models.Model):
track_cedh = models.BooleanField(default=True)
track_wincon = models.BooleanField(default=True)
track_tournament = models.BooleanField(default=True)
track_medium = models.BooleanField(default=True)
track_note = models.BooleanField(default=True)
user = models.ForeignKey(User,
max_length=100,
on_delete=models.CASCADE,
null=True)
def __str__(self):
return str(self.user)
HTML
<div class = "container shadow-md p-5 form-layout">
<h1 class = "">Update Tracking</h1>
<form action = ""
method = "POST"
autocomplete = "off">
{% csrf_token %}
{{ user }}
<br>
{{ form.track_cedh|as_crispy_field }}
{{ form.track_wincon|as_crispy_field }}
{{ form.track_tournament|as_crispy_field }}
{{ form.track_medium|as_crispy_field }}
<br>
<br>
<input class = "btn btn-primary"
type = "submit"
name = ""
value = "Submit">
<br>
</form>
</div>
Я попытался вставить пользователя в представление track_pref, как показано ниже, но получаю сообщение «аргумент типа «Пользователь» не повторяется»
@login_required(login_url='my-login')
def track_pref(request):
user = User.objects.get(username=request.user)
print(user)
if request.method == "POST":
print('first if')
form = UpdateTrackPrefForm(request.user, request.POST)
if form.is_valid():
print('Form Valid')
obj = form.save(commit=False)
obj.user = user
obj.save()
return HttpResponseRedirect('/view-games')
else:
print("else statement")
form = UpdateTrackPrefForm(request.user)





То, как вы пытаетесь включить пользователя в форму, которая не ожидает двух аргументов (form = UpdateTrackPrefForm(request.user, request.POST)), а также то, как вы пытаетесь получить User, может быть проблемой (user = User.objects.get(username=request.user). request.user — это User, а username — НЕТ. Попробуйте этот:
# views.py
@login_required(login_url='my-login')
def track_pref(request):
# The following are not needed, but the first is incorrect anyway
# user = User.objects.get(username=request.user)
# print(user)
track_pref = TrackPref.objects.get(user=request.user)
form = UpdateTrackPrefForm(instance=track_pref)
if request.method == "POST":
print('first if')
form = UpdateTrackPrefForm(request.POST, instance=track_pref) # NOTE THE CHANGE HERE
if form.is_valid():
print('Form Valid')
form.save(commit=False)
return HttpResponseRedirect('/view-games')
else:
print("else statement")
# or, to troubleshoot,
print((form.errors)
# THIS IS NOT NEEDED
# form = UpdateTrackPrefForm()
context = {'form': form, 'user': user, }
return render(request, 'gametracker_app/track-preference.html', context=context)
Установка instance=track_pref должна получить обновляемый TrackPref вместо создания нового экземпляра.
Кроме того, я не уверен, что ForeignKey — это то, что вам нужно, поскольку я думаю, что каждый TrackPref связан только с одним User, а ForeignKey — это ManyToOne отношение. Возможно, лучше использовать OneToOneField:
# models.py
class TrackPref(models.Model):
track_cedh = models.BooleanField(default=True)
track_wincon = models.BooleanField(default=True)
track_tournament = models.BooleanField(default=True)
track_medium = models.BooleanField(default=True)
track_note = models.BooleanField(default=True)
# NOTE THE CHANGE HERE
user = models.OneToOneField(User,
max_length=100,
on_delete=models.CASCADE,
null=True)
def __str__(self):
return str(self.user)
Редактировать
На самом деле вам даже не нужен оператор else, кроме как для того, чтобы вызвать ошибку, или сообщить пользователю о наличии ошибки, или просто распечатать ошибки для себя для устранения неполадок. Моя ошибка заключалась в том, что я вообще не рассматривал оператор else, который не нужен, за исключением того, что я только что объяснил.
Я обновил ответ @bld-sync, чтобы выполнить обновление формы вместо создания нового экземпляра в базе данных. Надеюсь, это сработает так, как вы задумали.
Мне жаль, что этот ответ так запоздал. Проблемы ИРЛ. Но это не помогло. Он не только не показывает текущие настройки пользователя, но и не обновляет экземпляр предпочтений при отправке формы.
Да, @bld-sync, ты прав. Я пренебрег изменением оператора else, который, как я объясняю, хорошо иметь в своем редактировании и в отредактированном коде, но в этом нет необходимости. Но я рад, что у вас все получилось так, как вы хотели, и рад, что помог.
Хотя Рафаэль подвел меня очень близко, в конечном итоге это сработало. Но это было отличное предложение изменить модель TrackPref на OneToOneField.
view.py
@login_required(login_url='my-login')
def track_pref(request):
track_pref = TrackPref.objects.get(user=request.user)
form = UpdateTrackPrefForm(instance=track_pref)
if request.method == "POST":
form = UpdateTrackPrefForm(request.POST, instance=track_pref)
if form.is_valid():
obj = form.save(commit=False)
obj.user = request.user
obj.save()
# I needed to go back to my previous code here
return HttpResponseRedirect('/view-games')
else:
form = UpdateTrackPrefForm(instance=track_pref)
# In this line, the call to get the user's preferences
# needed to be made to see their current preferences.
context = {'form': form, }
return render(request, 'gametracker_app/track-preference.html', context=context)
Итак, это еще не сделало то, что я искал. Вместо отображения текущих настроек он выводит пустую форму. Затем, когда вы отправляете форму, вместо обновления настроек она создает новый экземпляр в базе данных.