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

win*_*aed 4 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)
Run Code Online (Sandbox Code Playgroud)

我在网上看到了不同的参考资料,我是否应该使用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']
Run Code Online (Sandbox Code Playgroud)

这是我的观点:

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))     
Run Code Online (Sandbox Code Playgroud)

(是的,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>
Run Code Online (Sandbox Code Playgroud)

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

有人认为这种User关系可能会导致问题吗?


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

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

是否需要更改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))     
Run Code Online (Sandbox Code Playgroud)

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

<table border='1'>
    {% for field in form%}
        <tr>
            <td>{{field.label}}</td>
            <td>{{field.value}}</td>
        </tr>
    {% endfor%}
</table>
Run Code Online (Sandbox Code Playgroud)

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

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

Dan*_*man 16

我不确定这里究竟是什么问题,但一个问题肯定是你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()
Run Code Online (Sandbox Code Playgroud)

至于ForeignKey和OneToOne,你绝对应该使用OneToOne.关于使用ForeignKeys的建议在Django 1发布之前已经有一段时间 - 差不多五年前了 - 因为OneToOne的最初实现很差,并且它应该被重写.您肯定找不到任何有关FK使用的最新文档.

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

您应该回到在if语句中实例化表单的原始模式- 但是request.POSTelse子句中执行它时一定不要传递.