Django-profiles 自定义创建/编辑 modelForm 未正确保存

Posted

技术标签:

【中文标题】Django-profiles 自定义创建/编辑 modelForm 未正确保存【英文标题】:Django-profiles custom create/edit modelForm not saving properly 【发布时间】:2010-07-21 15:59:42 【问题描述】:

总结:

u = self.instance.user

def save(self, *args, **kwargs):
  u = self.instance.user
  u.first_name = self.cleaned_data['first_name']
  u.last_name = self.cleaned_data['last_name']
  u.save()
  return super(ProfileForm, self).save(*args, **kwargs)

导致问题,因为 self.instance 不存在。但是,在其他示例中,这就是它的完成方式,它似乎可以工作。我错过了什么?

继续阅读以了解更多信息 ->

我同时使用 django-registration 和 django-profiles。为了让它工作,我没有向配置文件模型(扩展用户的那个)添加任何额外的字段。到目前为止,它看起来像这样:

class sumaConnectUser(models.Model):

    user = models.ForeignKey(User)

    def __unicode__(self):
        return self.user.first_name + " " + self.user.last_name

    def get_absolute_url(self):
        return ('profiles_profile_detail', (),  'username': self.user.username )
    get_absolute_url = models.permalink(get_absolute_url)

到目前为止,我的理解是,我的用户“个人资料”应该只包含 contrib.auth 模型用户附带的字段。 (名字,姓氏等)

在我的 urls.py 中,我传递了用于创建和编辑配置文件的自定义表单-

(r'^profiles/edit', 'profiles.views.edit_profile', 'form_class': ProfileForm, ),
(r'^profiles/create', 'profiles.views.create_profile', 'form_class': ProfileForm, ),                   
(r'^profiles/', include('profiles.urls')),

最后,这是我的个人资料表格-

from suma.sumaconnect.models import sumaConnectUser
from django import forms
from django.contrib.auth.models import User

class ProfileForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
    super(ProfileForm, self).__init__(*args, **kwargs)
    try:
        self.fields['first_name'].initial = self.instance.user.first_name
        self.fields['last_name'].initial = self.instance.user.last_name
    except User.DoesNotExist:
        pass

first_name = forms.CharField(label="First Name")
last_name = forms.CharField(label="Last Name")

class Meta:
  exclude = ('user',)
  model = sumaConnectUser

def save(self, *args, **kwargs):
  u = self.instance.user
  u.first_name = self.cleaned_data['first_name']
  u.last_name = self.cleaned_data['last_name']
  u.save()
  return super(ProfileForm, self).save(*args, **kwargs)

我的目标是允许用户在个人资料编辑过程中编辑他们的名字和姓氏,但不能编辑他们的用户名和密码。

我考虑过更换

u = self.instance.user

u = User.objects.get(user = self.cleaned_data['username'])

但这需要我在我不想显示的页面上包含用户名 = forms.CharField。据我了解,当我进入创建个人资料或编辑个人资料页面时,我应该会自动编辑与我登录的用户关联的个人资料。

当我来到这个创建或编辑用户页面时,用户模型已经存在,但配置文件不存在。这是问题的原因吗?我想我误解了一些重大的事情,我将非常感谢任何关于我哪里出错的指示。谢谢!

【问题讨论】:

【参考方案1】:

您可以根据需要复制字段,并像上面一样对它们进行双重更新,但这不是配置文件的目的。它应该处理不在原始 auth.User 中的字段,因为您不需要直接编辑该模型。您在上面提到了“扩展用户”-您实际上并没有从 auth.User 继承,是吗?我强烈不建议这样做。

更新:

见this reference material。它使用与您在配置文件中进行用户更新相同的语法。

更新 2:

该示例用于编辑个人资料,而不是创建个人资料。查看 profile.views.create_profile 中的代码:

if request.method == 'POST':
    form = form_class(data=request.POST, files=request.FILES)
    if form.is_valid():
        profile_obj = form.save(commit=False)
        profile_obj.user = request.user
        profile_obj.save()

所以它首先保存表单,然后设置用户,然后保存配置文件。

这意味着你不能在 form.save 中设置用户值,你需要在配置文件的 model.save 中进行设置:

# in sumaConnectUser:

from django.db.models.base import ObjectDoesNotExist
class sumaConnectUser(models.Model):
  ...
  def save( self, *args, **kwargs ):
    s = super(sumaConnectUser,self).save( *args, **kwargs )
    try:
      u = s.user
      u.first_name = self.first_name
      u.last_name  = self.last_name
      u.save()
    except ObjectDoesNotExist:
      pass
    return s

基本上,通过查看 profile.views.create_profile 中的代码,我们肯定最终在配置文件上调用保存之后它设置了user。这可能不是第一次,所以我们需要抓住那个案例并忘记它。因为最终,它会被调用并触发我们保存到用户的代码。结果是,无论您将来为此用户配置文件采用何种形式,它都将始终保存回基础用户。

【讨论】:

我不是从 auth.User 继承,而是通过配置文件模型中的 ForeignKey 字段扩展它。我知道你说过我不应该双重更新任何东西,但在我看来,这不像我。我的意思是,我想要的只是让用户能够编辑 auth.User 模型的 first_name 和 last_name 属性。因此,我在表单中包含了这两个字段。然后我将它们分配给用户中的适当字段并在保存整个配置文件之前将其保存。当你说尝试使用 super.save 时,你的字面意思是把“super.save()”作为保存函数的第一行吗? 对不起,正在写速记。我的意思是你写的超级电话。在这种特殊情况下,复制字段没有错,恕我直言,否则您需要有两个表单和/或编辑 auth.User。 所以我尝试将“profile = super(ProfileForm, self).save(*args, **kwargs)” 放在函数的最顶部,然后将“return profile”放在函数的最底部,但我仍然在“u = self.instance.user”行收到“DoesNotExist at /profiles/create”错误。甚至 self.instance 都不存在。这是否意味着我需要第一次实例化配置文件? 超级保存调用返回一个实例,尝试使用它作为实例而不是self.instance。然后在底部返回超级保存调用给你的任何内容...... def save(self, *args, **kwargs): profile = super(ProfileForm, self).save(*args, **kwargs) u = profile.user u.first_name = self. clean_data['first_name'] u.last_name = self.cleaned_data['last_name'] u.save() return profile 给了我同样的 DoesNotExist 错误。我认为与其尝试随机的事情,不如尝试真正了解正在发生的事情。感谢您到目前为止的帮助,我非常感谢您的时间。上面的第一行保存配置文件。这个配置文件应该有一个用户属性,但没有,因为 profile.user 失败。对吗?

以上是关于Django-profiles 自定义创建/编辑 modelForm 未正确保存的主要内容,如果未能解决你的问题,请参考以下文章

包装第 3 方 Django 应用程序的视图时出错? (Facebook、django-socialregistration、django-profiles)

使用 TypeScript,React,ANTLR 和 Monaco Editor 创建一个自定义 Web 编辑器

Confluence 6 编辑自定义 Decorators

Confluence 6 编辑自定义 Decorators

肯蒂科 10 |自定义组件中富文本编辑器的工具栏

Wordpress 限制编辑,但允许预览自定义帖子状态