【问题标题】:Django ModelForm not saving data to databaseDjango ModelForm 没有将数据保存到数据库
【发布时间】:2013-08-19 11:47:39
【问题描述】:

这里的 Django 初学者在表单工作时遇到了很多麻烦。是的,我已经完成了本教程并浏览了很多网络 - 我所拥有的是我在这里和其他网站上找到的内容。我正在使用 Python 2.7 和 Django 1.5。 (虽然官方文档内容很丰富,但它倾向于假设您已经知道其中的大部分内容 - 不适合作为初学者参考,甚至不适合作为高级教程)

我正在尝试为“扩展”用户详细信息创建一个表单 - 例如。公司名称、街道地址等,但表格数据未保存到数据库中。

最初,我尝试创建一个扩展标准 User 模型的模型,但我放弃了 - 需要修改太多,而且在这个阶段它已经进入了超出我能力范围的细节。 因此,我创建了一个名为UserProfile 的新模型:

class UserProfile(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, unique=True) 
    company = models.CharField(max_length=50, blank=True)
    address1 = models.CharField(max_length=50, blank=True)
    address2 = models.CharField(max_length=50, blank=True)
    city = models.CharField(max_length=20, blank=True)
    region = models.CharField(max_length=20, blank=True)
    postcode = models.CharField(max_length=10, blank=True)
    country = models.CharField(max_length=20, blank=True)
    phone = models.CharField(max_length=30, blank = True)

我在网上看到了不同的参考资料,关于我应该使用ForeignKey(如上)还是使用 OneToOne 链接到 User 模型。

我正在尝试使用 ModelForm(保持简单,因为应该是简单的表单)。这是我的forms.py

from django.forms import ModelForm
from .models import UserProfile   

class UserDetailsForm(ModelForm):
    class Meta:
        model = UserProfile
        fields = ['company','address1','address2','city','region', 'postcode','country','phone']

这是我的看法:

def UserDetailsView(request):
    #f = 0
    if request.method == 'POST':
        f = UserDetailsForm(request.POST, instance = request.user)
        if f.is_valid():
            f.save()
    else:
        f = UserDetailsForm(request.POST , instance = request.user)

    print "UserDetails objects: ", (UserProfile.objects.all()) 

    return render_to_response('plagweb/console/profile.html', 
                              { 'form': f}, 
                              context_instance=RequestContext(request))     

(是的,UserProfile 与 UserDetail 之间存在不一致 - 这是我所有黑客行为的产物,一旦我开始工作就会修复)

诊断显示 f.is_valid() 返回 True。 同样,诊断显示UserProfile.objects.all() 为空。我在上面的视图中在 save() 之后尝试过这个,也在 Django 控制台上尝试过。

这是我的模板:

 <form method="POST" action="">
 <table>{{ form }}</table>
 <input type="submit" value="Update" />
 {% csrf_token %}
 </form>

目前的主要问题是表单数据没有保存到数据库中。我不知道是否正在读取(一旦我在数据库中有一些数据......)

一个想法是User 关系可能会导致问题?


继 Daniel Roseman 的有用评论/帮助之后的附录:

现在表单正在正确保存(通过诊断和命令行检查确认。但是当我返回表单时,它不显示现有数据。显示一个带有空数据字段的表单。据我所知,我正确地传递了实例数据。

是否有需要更改的 ModelForm 设置?

这是修改后的视图:

def UserDetailsView(request):
    #print "request co:", request.user.profile.company
    f = UserDetailsForm(request.POST, instance = request.user.profile )

    if request.method == 'POST':
        if f.is_valid():
            profile = f.save(commit=False)
            profile.user = request.user
            profile.save()

    return render_to_response('plagweb/console/profile.html', 
                              { 'form': f}, 
                              context_instance=RequestContext(request))     

诊断显示request.user.profile 设置正确(特别是公司字段)。但是,表单显示为空字段。 HTML 源代码也不显示任何数据值。 作为额外检查,我还尝试了一些模板诊断:

<table border='1'>
    {% for field in form%}
        <tr>
            <td>{{field.label}}</td>
            <td>{{field.value}}</td>
        </tr>
    {% endfor%}
</table>

这会正确列出字段标签,但值都报告为None

为了完整起见,UserProfile 的用户字段现在定义为 user = models.OneToOneField(settings.AUTH_USER_MODEL),并且 User.profile lambda 表达式未更改。

【问题讨论】:

  • 也许可以尝试取出if f.is_valid(),看看当你尝试保存它时它可能会抛出什么异常。
  • 它不会抛出任何异常。我的诊断也显示 is_valid() 返回 true

标签: django django-models django-1.5


【解决方案1】:

无论您尝试在哪里向 Django 代码提交表单数据,Django 都会为整个表单数据创建一个对象。对象看起来像这样form_obj = request.method_name。这里method_name 是表单方法(POST 或 GET) 例如:- form_obj = request.POST

如果要获取表单数据,请使用函数 request.method_name.get(name) 这里 name 是表单属性赋值

例如:-

<form method="post">
{% csrf_token %}
{form}
</form>

在视图中:-

import statements as you required
def your_function(request):
  # you can creat a object to the form by
  form_obj = myform()
  if request.method =="POST":
    form_obj = myform(request.POST)
    if form_obj.is_valid():

      # you can directly save by use commit()
      form_obj.save(commit=True)
       #   or
      form_obj1 = form_obj.save(commit=False)
      #which  do you want to save in database ,those fields you need to specify like below 
      form_obj1.attribute1 = form_obj.cleaned_data["name of form field"]
        '
        '
      form_obj1.save()

在 Myform.py 文件中

import statments    
class myform(forms.ModelForm):
    class meta():
        model = your_models_name
        fields =("attribute1","attribute2".....) # included attribute of your_model

【讨论】:

    【解决方案2】:

    我认为您需要首先为 ModelForm 创建一个对象,然后在请求方法为 post 时分配该对象。 在您的代码中,您只对一个属性执行此操作,并且在检查方法之前。 - 同样在您的 forms.py 中,在 Meta() 类的 fields 参数中,您使用了 [] 括号来指示必须排除哪些属性,但是当您在表单中包含所有这些属性时,您必须使用 () 括号。 我认为你的代码应该编辑如下:

    see here

    【讨论】:

      【解决方案3】:

      记得将您的模型表格注册到admin.py 文件。这是一个常见的错误

      在此处注册您的模型。

      from . models import advancedUserForm
      admin.site.register(advancedUserForm)
      

      【讨论】:

        【解决方案4】:

        这是一种旧线程,但我希望这会对某人有所帮助。 我一直在努力解决类似的问题,我从 db 启动对象,更新字段,调用 save() 函数,但什么也没发生。

        user = User.objects.get(username = example_string)
        user.userprofile.accepted_terms = True
        user.userprofile.save()
        

        最近添加了字段accepted_terms,这就是问题所在。首先尝试python manage.py makemigrationspython manage.py migrate,如果这不能帮助您需要刷新数据库。

        解决方案在我的例子中是刷新数据库

        【讨论】:

          【解决方案5】:

          我不确定到底是什么问题,但一个问题肯定是您在实例化表单时传递了instance=request.user。这绝对是错误的:request.user 是 User 的一个实例,而表单基于 UserProfile

          相反,你想做这样的事情:

          f = UserDetailsForm(request.POST)
          if f.is_valid():
              profile = f.save(commit=False)
              profile.user = request.user
              profile.save()
          

          关于 ForeignKey 与 OneToOne,您绝对应该使用 OneToOne。使用 ForeignKeys 的建议是在 Django 1 发布前一段时间给出的——现在差不多五年前了——因为 OneToOne 的原始实现很差,它应该被重写。您肯定不会在此处找到任何建议使用 FK 的最新文档。

          在 cmets 之后编辑 现在的问题是,您正在使用第一个参数 data 来实例化表单,即使请求不是 POST 并且因此 request.POST 是一个空字典。但是 data 参数,即使它是空的,也优先于作为初始数据传递的任何内容。

          您应该回到在 if 语句中实例化表单的原始模式 - 但在 else 子句中执行此操作时请确保不要传递 request.POST

          【讨论】:

          • 重新。 ForeignKey:我认为这突出了我的问题的很大一部分。博客、stackoverflow 等中有很多东西,但它涵盖了从 1.0 到 1.5 的所有内容,而且并不总是清楚正在处理哪个版本。甚至 Apress 书 (Holovaty&Kaplan-Moss) 也有最新版本“针对 1.1 进行了修改”。我敢肯定,一旦我进一步深入,这一切都会变得有意义,但对于那些处于学习曲线中的人来说,这会让人感到困惑!
          • 重新。 request.user:这似乎已经修复了保存。 UserProfile.objects.all() 返回一个对象,在命令行中,我可以读取我的一个字段!这样就解决了我的直接问题。现在我需要在加载表单时加载该数据。看起来我需要处理第二个 UserDetailsForm 构造函数...
          • 不,不需要新的构造函数:只需将 UserProfile 传递为 instance
          • 我目前将构造函数设置为: f = UserDetailsForm(request.POST, instance = request.user.profile) 这似乎正确地进行了更新(通过命令行检查),但它没有t 将现有数据加载到表单中。我在想 RequestContext 可能不正确?
          • 我已经在我的问题中添加了一个附录,并更新了到目前为止的代码。现在正在保存数据(谢谢!)。回到表单,数据正在加载,但它没有显示在 ModelForm 中。
          【解决方案6】:
          UserDetailsForm(request.POST, instance = db_obj_form)
          

          db_obj 应该是您要保存的表 UserProfile 的对象。

          【讨论】:

            猜你喜欢
            • 2020-10-11
            • 1970-01-01
            • 2018-07-07
            • 2018-10-10
            • 1970-01-01
            • 2011-02-19
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多