Django form.is_valid не работает и не сохраняет форму
Моя модель аккаунта автоматически создается, когда пользователь создает новый аккаунт & в эту модель добавляется только значение пользователя, остальное остается пустым! Я пытаюсь заставить пользователя обновить или добавить больше информации в модель аккаунта, но is.valid() не работает в представлениях & не сохраняет форму. что пошло не так & как это исправить?
#model.py
class profile(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
bio = models.TextField(blank=True, null=True, max_length=100)
profile_img = models.ImageField(
upload_to="profile_images", default="default.jpg")
location = models.CharField(max_length=100, blank=True)
def __str__(self):
return self.user.username
#form.py
class accountForm(ModelForm):
class Meta:
model = profile
fields = "__all__"
widgets = {
# 'fields': forms.TextInput(attrs={'class': "form-control"}),
'profile_img': forms.FileInput(attrs={'class': 'form-control', 'id': 'inputGroupFile04'}),
'bio': forms.Textarea(attrs={'class': 'form-control'}),
'location': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Location'}),
}
#views.py
def account(request):
Profile = profile.objects.get(user=request.user)
form = accountForm(instance=Profile)
if request.method == "POST":
form = accountForm(request.POST, instance=Profile)
if form.is_valid():
form.save()
return redirect("sign_in")
context = {"form": form}
return render(request, "account.html", context)
Я бы внедрил некоторую обработку ошибок в ваше представление. У вас есть
if form.is_valid:
но не больше. Поэтому ошибки не отображаются на странице
Обычно, когда это происходит со мной, я бросаю отладочный оператор сразу после вызова .is_valid()
import ipdb; ipdb.set_trace()
Затем в полученном терминале я наберу form.errors
и вы увидите, что пошло не так
Во-первых, чтобы загрузить файлы, вам нужно убедиться, что ваш элемент правильно определяет enctype как "multipart/form-data" в теге формы:
#templates file
<form enctype="multipart/form-data" method="post" action="/foo/">
Во-вторых, добавьте request.FILES в form = accountForm(request.POST, request.FILES, instance=Profile)
Подробнее об этом вы можете прочитать в django docs
Для сохранения формы можно использовать cleaned_data
.
Попробуйте этот вид:
views.py
def account(request):
profile_instance = profile.objects.get(user=request.user)
form = accountForm(instance=profile_instance)
if request.method == "POST":
form = accountForm(request.POST, instance=profile_instance)
if form.is_valid():
user = request.user
bio = request.POST.get('bio')
profile_img = request.POST.get('profile_img')
location = request.POST.get('location')
profile.objects.create(
user=user, bio=bio, profile_img=profile_img, location=location)
return redirect("sign_in")
else:
form = accountForm()
return render(request, "home/account.html", {'form': form})
Note:
Модели пишутсяPascalCase
, а неsmallcase
, поэтому будет лучше, если вы назовете ееProfile
вместо. То же самое касается форм, лучше, если вы напишитеprofile
AccountForm
, или еще лучшеProfileForm
вместо.accountForm
Спасибо всем за предложения, но я понял, в чем проблема. Извините, что не предоставил html-коды, потому что я не добавил туда тег forms.user. Поэтому request.POST не предоставлял пользователя. Есть два способа исправить это. Вы можете использовать отношение onetoone в models.py, что не обязательно потребует выбора пользователей. Следующий способ более эффективен, а именно, в forms.py скрыть форму пользователя по:
class accountForm(ModelForm):
class Meta:
model = profile
fields = "__all__"
widgets = {
user': forms.hiddenInput(),
'profile_img': forms.FileInput(attrs={'class': 'form-control', 'id': 'inputGroupFile04'}),
'bio': forms.Textarea(attrs={'class': 'form-control'}),
'location': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Location'}),
}
затем, добавьте пользователя в views.py через INITIAL следующим образом :
def account(request):
form = accountForm(initial=request.user)
if request.method == "POST":
form = accountForm(request.POST, initial = request.user)
if form.is_valid():
form.save()
return redirect("sign_in")
context = {"form": form}
return render(request, "account.html", context)
если вы хотите обновить его, используйте instance вместо initial & предоставьте профиль там