【问题标题】:Editing the saved user profile in django在 django 中编辑保存的用户配置文件
【发布时间】:2019-07-11 07:31:18
【问题描述】:

我使用 django 用户模型创建了一个注册表单,并添加了一个额外的字段 confirm_pwd。我创建了一个编辑页面来编辑特定用户的详细信息。编辑后我需要在个人资料页面中显示个人资料详细信息。我也创建了个人资料页面。但它仅在用户注册或登录时显示。当我编辑详细信息后单击保存按钮将重定向到个人资料页面。此时个人资料页面不显示详细信息。这是我的代码

models.py

from django.db import models
from django.contrib.auth.models import User


class UserProfileInfo(models.Model):
    user = models.OneToOneField(User,on_delete=models.CASCADE)

    def __str__(self):
        return self.user.username

forms.py

from django import forms
from django.forms import ModelForm
from .models import UserProfileInfo
from django.contrib.auth.models import User
class EditProfileForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
confirm_pwd = forms.CharField(widget=forms.PasswordInput())
class Meta():
    model = User
    fields = ['first_name','last_name','username','email','password']
    help_texts={
        'username': None
    }
def clean(self):
    cleaned_data = super(EditProfileForm, self).clean()
    password = cleaned_data.get("password")
    confirm_password = cleaned_data.get("confirm_pwd")
    print(confirm_password)

    if password != confirm_password:
        print("yes")
        raise forms.ValidationError(
            "password and confirm_password does not match"
        )  

views.py

from django.shortcuts import render
from django.http import HttpResponseRedirect, HttpResponse
from .models import UserProfileInfo
from django.contrib.auth.models import User
from .forms import UserForm,UserProfileInfoForm,GithubInfo,EditProfileForm
from django.contrib.auth import authenticate, login, logout
from django.urls import reverse
@login_required
def edit_profile(request):
    if request.method == 'POST':
        form = EditProfileForm(request.POST, instance=request.user)
        if form.is_valid():
            user = form.save(commit=False)
            user.set_password(form.cleaned_data['password'])
            user.save()
            return HttpResponseRedirect(reverse('signupapp:profile'))
    else:
        form=EditProfileForm(instance=request.user)
    return render(request, "signupapp/edit_profile.html", {'form':form })

edit_profile.html

<form method="POST" action="" class="" >
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Save</button>
</form>

profile.html

{% if user.is_authenticated %}
<h1>Welcome!</h1>
<h3>Firstname: {{ user.first_name }}</h3>
<h3>Lastname: {{ user.last_name }}</h3>
<h3>Username: {{ user.username }}</h3>
<h3>Email: {{ user.email }}</h3>
<a href="{% url 'signupapp:edit' %}"><input type="button" value="Edit"/></a>
<a href="{% url 'signupapp:delete' request.user.id %}"><input type="button" value="Delete"/></a><br>
<br>
{% else %}
<h3>Register or Login if you'd like to</h3>
{% endif %}

当我在服务器中运行此代码时,个人资料页面不显示用户详细信息。

我怎样才能做到这一点。 提前致谢。

【问题讨论】:

    标签: django


    【解决方案1】:

    在您的views.py 中,您从request.user 获取user 并尝试为confirm_pwd 分配一个新值。但是,user 没有 confirm_pwduser 是 Django 用户,而不是您的 UserProfileInfo。通过删除views.py 上的以下行,它应该可以工作。此外,您不需要保存密码确认,那应该只是为了检查目的。

    # to be removed
    user.confirm_pwd = request.POST['confirm_pwd']
    

    【讨论】:

    • 错误不在user.confirm_pwd = ...处,其实这完全没有问题,因为它会动态添加一个额外的属性。它位于initial={...}中的user.confirm_pwd
    【解决方案2】:

    您自己实现了很多逻辑,ModelForm 应该处理这些逻辑。 ModelForm 的主要目的之一就是无需大量样板逻辑即可创建和编辑模型对象。

    目前还不清楚您为什么要使用第二种形式。尤其是因为您不渲染它,也不用它做太多事情。所以放弃这种形式可能更有意义。

    您的EditProfileForm 确实包含对不是该类超类的类的超级调用,您应该使用super(ModelForm, self),而不是super(UserForm, self)

    class EditProfileForm(forms.ModelForm):
    
        # ...
    
        def clean(self):
            cleaned_data = super(ModelForm, self).clean()
            # ...
            return cleaned_data

    主要问题是您使用以下方式初始化表单:

    pform = UserProfileInfoForm(request.POST or None, initial={'confirm_pwd': <s>user.confirm_pwd</s>})

    因为user 没有confirm_pwd 字段或属性或属性。

    此外,User 模型保存原始密码。这些密码经过哈希处理,以避免黑客在设法访问数据库时检查密码。

    您可以通过以下方式实现您的视图:

    from django.contrib.auth.decorators import login_required
    from django.shortcuts import redirect
    
    @login_required
    def edit_profile(request):
        if request.method == 'POST':
            form = EditProfileForm(request.POST, instance=request.user)
            if form.is_valid():
                user = form.save(commit=False)
                user.set_password(form.cleaned_data['password'])
                user.save()
                return redirect('signupapp:profile')
        else:
            form=EditProfileForm(instance=request.user)
        return render(request, "signupapp/edit_profile.html", {'form':form })

    修补__init__EditProfileForm 可能会更好,因为现在它将使用密码的散列版本初始化密码字段。因此,这与输入的密码不同,而且它还暴露了数据库中可能应该保持安全的一些数据。

    【讨论】:

    • 这样做会在 /edit/ super(type, obj) 处显示错误 TypeError: obj must be an instance or subtype of type
    • @BinduMachani:那是因为你的cleaned_data = super(UserForm, self).clean() password = cleaned_data.get("password") 行,你的表单不是UserForm,而是ModelForm
    猜你喜欢
    • 1970-01-01
    • 2014-04-29
    • 2012-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-05
    • 2018-02-20
    相关资源
    最近更新 更多