这里的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表达式未更改。
答案 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 makemigrations
和python 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参数中,您使用了[]方括号,该括号指示必须排除哪些属性,但是在以表格形式包含所有这些属性时,必须使用()方括号。 我认为您的代码应进行如下修改:
答案 5 :(得分:0)
无论您尝试将表单数据提交到Django代码,还是Django都会为整个表单数据创建一个对象。该对象看起来像form_obj = request.method_name
。 method_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