Django ModelForm没有将数据保存到数据库

时间:2013-08-17 00:45:21

标签: django django-models django-1.5

这里的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链接到用户模型。

我正在尝试使用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表达式未更改。

6 个答案:

答案 0 :(得分:15)

我不确定这里究竟是什么问题,但一个问题肯定是你在实例化表单时传递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的最新文档。

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

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

答案 1 :(得分:1)

这是一种旧线程,但是我希望这会对某人有所帮助。 我一直在努力解决类似的问题,我从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

在我的情况下,

解决方案刷新数据库

答案 2 :(得分:0)

UserDetailsForm(request.POST, instance = db_obj_form)

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

答案 3 :(得分:0)

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

在此处注册您的模型。

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

答案 4 :(得分:0)

我认为您首先需要为ModelForm创建一个对象,然后在请求方法为post的情况下为其分配对象。 在您的代码中,仅对一个属性执行此操作,然后再检查方法。 -同样在您的form.py中,在Meta()类的fields参数中,您使用了[]方括号,该括号指示必须排除哪些属性,但是在以表格形式包含所有这些属性时,必须使用()方括号。 我认为您的代码应进行如下修改:

see here

答案 5 :(得分:0)

无论您尝试将表单数据提交到Django代码,还是Django都会为整个表单数据创建一个对象。该对象看起来像form_obj = request.method_namemethod_name是此处的表单方法(POST或GET) 例如:-form_obj = request.POST

如果要获取表单数据,请使用函数request.method_name.get(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