简体   繁体   English

django form.is_valid 失败且不保存表单

[英]django form.is_valid is failing & not saving the form

My account model automatically creates when user creates a new user account & only user value is added to that model, rest remains empty!当用户创建新的用户帐户时,我的帐户模型会自动创建,并且仅将用户值添加到该模型中,其余部分保持为空! i am trying to make the user update or add more info in their account model but the is.valid() is failing in views & not saving the form.我正在尝试让用户更新或在他们的帐户模型中添加更多信息,但是 is.valid() 在视图中失败并且没有保存表单。 what went wrong & how to fix it?出了什么问题以及如何解决?

Models.py模型.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

Forms.py表格.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视图.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)

I would impliment some error handling in your view.我会在您的观点中暗示一些错误处理。 You have an你有一个

if form.is_valid: statement but no else. if form.is_valid:声明,但没有别的。 That's why errors are not showing up on the page这就是页面上没有显示错误的原因

Usually when this happens to me I drop a debugger statement right after the call to .is_valid()通常当这种情况发生在我身上时,我会在调用 .is_valid() 之后立即删除一个调试器语句

import ipdb; ipdb.set_trace()

Then in the resulting terminal I will type form.errors and you should see what went wrong然后在生成的终端中,我将输入form.errors你应该看到出了什么问题

Firstly, in order to upload files, you'll need to make sure that your首先,为了上传文件,您需要确保您的element correctly defines the enctype as "multipart/form-data" in your form tag:元素在您的表单标签中正确地将enctype定义为“multipart/form-data”

#templates file
<form enctype="multipart/form-data" method="post" action="/foo/">

Secondly, add request.FILES to form = accountForm(request.POST, request.FILES, instance=Profile)其次,将request.FILES添加到form = accountForm(request.POST, request.FILES, instance=Profile)

You can read more about this from django docs您可以从django 文档中了解更多信息

You can use cleaned_data to save the form.您可以使用cleaned_data来保存表单。

Try this view:试试这个视图:

views.py视图.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})

Make sure, you are logged in and profile model does not contain two same users for working of above code, as you have made it Foreignkey .确保您已登录并且profile模型不包含两个相同的用户来处理上述代码,因为您已将其Foreignkey

Note: Models are written in PascalCase not smallcase , so it will be better if you name it as Profile instead of profile . Note:模型是用PascalCase而不是smallcase编写的,因此最好将其命名为Profile而不是profile Same goes for forms, better if you write AccountForm , or more better ProfileForm instead of accountForm .表单也是如此,如果您编写AccountForm会更好,或者使用ProfileForm而不是accountForm更好。




Try below code, in which profile will be created directlty.试试下面的代码,其中将直接创建配置文件。

models.py模型.py


class profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    # other fields are same...

In real scenario, it will be better to make user a OneToOneField in Profile model, as one person can only have one profile, I assumed you are creating users' profile first time, rather than updating the existing profiles, so I'll not use instance in form.在实际场景中,最好在Profile模型中将user设置为OneToOneField ,因为一个人只能拥有一个个人资料,我假设您是第一次创建用户的个人资料,而不是更新现有的个人资料,所以我不会使用形式上的instance

views.py视图.py

def account(request):
    if request.method == "POST":
        form = accountForm(request.POST)
        if form.is_valid():
            username = request.POST.get('username')
            password = request.POST.get('password1')
            bio = request.POST.get('bio')
            profile_img = request.POST.get('profile_img')
            location = request.POST.get('location')
            created_user = User.objects.create(
                username=username, password=password)

            profile.objects.create(
                user=created_user, bio=bio, profile_img=profile_img, location=location)
            return redirect('sign_in')
    else:
        form = accountForm()

    return render(request, "home/account.html", {'form': form})

forms.py表格.py

class accountForm(ModelForm):
    username = forms.CharField(
        widget=forms.TextInput(attrs={'class': 'form-control'}))
    password1 = forms.CharField(
        widget=forms.PasswordInput(attrs={'class': 'form-control'}))
    password2 = forms.CharField(
        widget=forms.PasswordInput(attrs={'class': 'form-control'}))

    def clean(self):
        cleaned_data = super().clean()
        p1 = cleaned_data.get('password1')
        p2 = cleaned_data.get('password2')
        if p1 != p2:
            raise forms.ValidationError('Both the passwords must match')

    class Meta:
        model = profile
        fields = ['username', 'password1',
                  'password2', 'profile_img', 'bio', 'location']
        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'}),

        }

It will create new users' profile directly, with password validation and those users also relate to User model, so you'll not get the error of the field user in profile model must be an user instance .它将直接创建新用户的个人资料,并进行密码验证,并且这些用户也与User模型相关,因此您不会得到the field user in profile model must be an user instance的错误。

thanks for everyones suggestions but i figured out what was the issue here.感谢大家的建议,但我想出了这里的问题。 sorry for not providing the html codes bcz i didn't added forms.user tag there .很抱歉没有提供 html 代码 bcz 我没有在那里添加 forms.user 标记。 so request.POST wasn't providing the user.所以 request.POST 没有提供给用户。 there are two ways to fix this.有两种方法可以解决这个问题。 you can use onetoone relation in models.py which will not necesarily need you to choose users.您可以在 models.py 中使用 onetoone 关系,这不一定需要您选择用户。 the next one is more efficient that is, in forms.下一个更有效,即形式上。 py hide the user form by: 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'}),

        }

then, add the user in views.py through INITIAL like :然后,通过 INITIAL 在 vi​​ews.py 中添加用户,例如:

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)

if you want to update it, use instance instead of initial & provide the profile there如果您想更新它,请使用实例而不是初始并在那里提供配置文件

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM