Django 访问通过表单上的OneToOneField模型链接的模型的数据

Django 访问通过表单上的OneToOneField模型链接的模型的数据,django,python-3.x,django-models,django-forms,django-views,Django,Python 3.x,Django Models,Django Forms,Django Views,我想要一个预填充的表单,其中包含登录用户的个人资料的详细信息(例如姓名),以便他们可以更新。我有一个带有名字和姓氏的自定义用户模型,然后是一个与用户模型链接并扩展的概要文件模型,其中包含一些额外的信息 我在profile模型中定义了一个常量,理论上应该得到用户的名字和姓氏 models.py: class User(AbstractBaseUser): email = models.EmailField(verbose_name="email", unique=True, max_len

我想要一个预填充的表单,其中包含登录用户的个人资料的详细信息(例如姓名),以便他们可以更新。我有一个带有名字和姓氏的自定义用户模型,然后是一个与用户模型链接并扩展的概要文件模型,其中包含一些额外的信息

我在profile模型中定义了一个常量,理论上应该得到用户的名字和姓氏

models.py:

class User(AbstractBaseUser):
    email = models.EmailField(verbose_name="email", unique=True, max_length=255)
    first_name = models.CharField(max_length=30, blank=True, null=True)
    surname = models.CharField(max_length=30, blank=True, null=True)
[...]
    objects = UserManager()

[...]
添加了配置文件模型

class Profile(models.Model):
    user = models.OneToOneField(User, related_name='current_user', on_delete=models.CASCADE)
    image = models.ImageField(default='default.jpg', upload_to='profile_pics')

    def surname(self):
        return self.user.surname}

    def first_name(self):
        return self.user.first_name
[...]
views.py:

@login_required
def profile_edit(request):
    if request.method == 'POST':

        p_form = ProfileUpdateForm(request.POST, request.FILES, instance=request.user.profile)

        if p_form.is_valid():

            p_form.save()
            messages.success(request, f'Your account has been updated')
[...]
u_form = UserUpdateForm(request.POST, instance=request.user)
p_form = ProfileUpdateForm(request.POST, request.FILES, instance=request.user.profile)
forms.py:

class ProfileUpdateForm(forms.ModelForm):
    class Meta:
        model = Profile
        fields = ('first_name', 'surname')
class UserUpdateForm(forms.ModelForm):

    class Meta:
        model = User
        fields = ('first_name', 'surname')

class ProfileUpdateFormOld(forms.ModelForm):

    class Meta:
        model = Profile
        fields = ('image',)
template.html:

{% extends "base.html" %}

{% block content %}

<div>
      <form method="POST" enctype="multipart/form-data">
          {% csrf_token %}

          {{ p_form }}
          <button class="button" type="submit"> User update</button>
      </form>
    </div>
{% endblock content %}
{{ u_form }}
{{ p_form }}
forms.py:

class ProfileUpdateForm(forms.ModelForm):
    class Meta:
        model = Profile
        fields = ('first_name', 'surname')
class UserUpdateForm(forms.ModelForm):

    class Meta:
        model = User
        fields = ('first_name', 'surname')

class ProfileUpdateFormOld(forms.ModelForm):

    class Meta:
        model = Profile
        fields = ('image',)
template.html:

{% extends "base.html" %}

{% block content %}

<div>
      <form method="POST" enctype="multipart/form-data">
          {% csrf_token %}

          {{ p_form }}
          <button class="button" type="submit"> User update</button>
      </form>
    </div>
{% endblock content %}
{{ u_form }}
{{ p_form }}

基本上,这些字段来自
User
model,它们不在
Profile
model中。因此,您可以将
ProfileUpdateForm
中的模型类更改为
User

class ProfileUpdateForm(forms.ModelForm):

    class Meta:
        model = User
        fields = ('first_name', 'surname')

根据评论更新答案:

class ProfileUpdateForm(forms.ModelForm):
    first_name = forms.CharField(max_length=255)
    surname = forms.CharField(max_length=255)

    def __init__(self, *args, **kwargs):
        super(ProfileUpdateForm, self).__init__(*args, **kwargs)
        self.initial['first_name'] = self.instance.first_name()
        self.initial['surname'] = self.instance.surname()

    class Meta:
        model = Profile
        fields = ('first_name', 'surname')

    def save(self, *args, **kwargs):
        user = self.instance.user
        user.first_name = self.cleaned_data.get('first_name')
        user.surname = self.cleaned_data.get('surname')
        user.save()
        return super(ProfileUpdateForm, self).save(*args, **kwargs)

替代方法是在初始化表单时发送初始数据,传递初始数据。例如: profile=request.user.profile

ProfileUpdateForm(instance=profile, initial={'first_name':profile.first_name(), 'surname': profile.surname()})

基本上,这些字段来自
User
model,它们不在
Profile
model中。因此,您可以将
ProfileUpdateForm
中的模型类更改为
User

class ProfileUpdateForm(forms.ModelForm):

    class Meta:
        model = User
        fields = ('first_name', 'surname')

根据评论更新答案:

class ProfileUpdateForm(forms.ModelForm):
    first_name = forms.CharField(max_length=255)
    surname = forms.CharField(max_length=255)

    def __init__(self, *args, **kwargs):
        super(ProfileUpdateForm, self).__init__(*args, **kwargs)
        self.initial['first_name'] = self.instance.first_name()
        self.initial['surname'] = self.instance.surname()

    class Meta:
        model = Profile
        fields = ('first_name', 'surname')

    def save(self, *args, **kwargs):
        user = self.instance.user
        user.first_name = self.cleaned_data.get('first_name')
        user.surname = self.cleaned_data.get('surname')
        user.save()
        return super(ProfileUpdateForm, self).save(*args, **kwargs)

替代方法是在初始化表单时发送初始数据,传递初始数据。例如: profile=request.user.profile

ProfileUpdateForm(instance=profile, initial={'first_name':profile.first_name(), 'surname': profile.surname()})

我不明白你所说的“轮廓模型中的常数”是什么意思。但这里的问题是,名字和姓氏是用户的字段,而不是个人资料;您应该在表单上设置
model=User
。@ruddra抱歉-我刚刚意识到我忘记了包含我的配置文件模型。我不明白您所说的“配置文件模型中的常数”是什么意思。但这里的问题是,名字和姓氏是用户的字段,而不是个人资料;您应该在表单上设置
model=User
。@ruddra抱歉-我刚刚意识到我忘了包括我的个人资料模型。但是我希望登录的用户访问他们的个人资料信息,其中包含更多的信息(如图片、简历等),而不是用户信息。我已经有了一个UserUpdateForm来执行您的建议。我希望用户能够更改来自其用户和配置文件模型的数据。谢谢,实际上,我只需向表单中添加另一个元类即可解决此问题,即:
class ProfileUpdateForm(forms.ModelForm):class Meta:model=user fields=('first_name','names'))class Meta:model=Profile fields=('image',)
不过我愿意尝试一下您的解决方案。现在,我得到了一个
super():无参数
错误。嗯,可能您不是python3用户。请看更新的答案。哎呀,我的错。我在代码上犯了一个错误。更新了我的答案OK,我的Python虚拟环境有点可疑。我删除了sqlite数据库和所有迁移,停用了虚拟环境,重新激活了虚拟环境,进行并应用了迁移,重新创建了用户等,现在终于可以工作了。谢谢但是我希望登录的用户访问他们的个人资料信息,其中包含更多的信息(例如图片、个人简历等),而不是用户信息。我已经有了一个UserUpdateForm来执行您的建议。我希望用户能够更改来自其用户和配置文件模型的数据。谢谢,实际上,我只需向表单中添加另一个元类即可解决此问题,即:
class ProfileUpdateForm(forms.ModelForm):class Meta:model=user fields=('first_name','names'))class Meta:model=Profile fields=('image',)
不过我愿意尝试一下您的解决方案。现在,我得到了一个
super():无参数
错误。嗯,可能您不是python3用户。请看更新的答案。哎呀,我的错。我在代码上犯了一个错误。更新了我的答案OK,我的Python虚拟环境有点可疑。我删除了sqlite数据库和所有迁移,停用了虚拟环境,重新激活了虚拟环境,进行并应用了迁移,重新创建了用户等,现在终于可以工作了。谢谢