如何在表单中正确引用用户模型
How to correctly reference the User model in a form
基本上,我正在尝试为我的网站提供一项功能,让人们可以在他们的用户帐户中注册一个电子小鬼(多个)。我的问题是我的 Device 模型,通过扩展我的 DeviceForm ModelForm 使用 ForeignKey 来引用用户对象。因此,当我去注册一个设备时,它会询问设备的名称、imp 的 agent_id、设备类型和与帐户关联的用户。我认为我的 is_valid() 验证失败的地方在于我如何引用用户模型。我不认为它是用户对象的 "valid" 输入。是否有其他方法可以使用用户的用户名 link 将设备连接到正确的帐户?
Models.py:
class Device(models.Model):
name = models.CharField(max_length=100)
agent_id = models.CharField(max_length=100)
device_type = models.CharField(max_length=100, choices=(
("imp", "Electric Imp P3V3"),
))
owner = models.ForeignKey(User)
def __unicode__(self):
return self.name
class DeviceForm(ModelForm):
class Meta:
model = Device
fields = ['name', 'agent_id', 'device_type', 'owner']
def clean_agent_id(self):
agent_id = self.cleaned_data['agent_id']
if Device.objects.exclude(pk=self.instance.pk).filter(agent_id=agent_id).exists():
raise forms.ValidationError(u'agent_id "%s" is already in use.' % agent_id)
return agent_id
Views.py:
def devices(request):
devform = DeviceForm(request.POST)
if devform.is_valid():
device_obj = devform.save()
device_obj.save()
return HttpResponseRedirect('deviceconfirmation')
else:
devform = DeviceForm()
return render_to_response('courses/devices.html', {'devform': devform}, context_instance=RequestContext(request))
devices.html:
{% extends "layout.html" %}
{% load static from staticfiles %}
{% block title %}{{ page.title }}{% endblock %}
{% block content %}
<article>
<div id="wrapper">
<p id="devicecreate">Register your device to your account:</p>
<form action="{% url 'courses:deviceconfirmation' %}" id="devform" method="post"> {% csrf_token %}
<p>
<label for="name">Device Name:</label>
<input id="name" name="name" type="text">
</p>
<p>
<label for="agent_id">Agent ID:</label>
<input id="agent_id" name="agent_id" type="text">
</p>
<p>
<label for="device_type">Imp Type:</label>
<select name="device_type" form="devform" id="selectbox">
<option value="imp">Imp Regular</option>
<option value="Electric Imp P3V3">Imp P3V3</option>
</select>
</p>
<p>
<label for="owner">Device Owner(username):</label>
<input id="owner" name="owner" type="text">
</p>
<p>
<input type="submit" value="REGISTER DEVICE" id="submit">
</p>
</form>
</div>
</article>
{% endblock %}
views.py 设备确认:
def deviceconfirmation(request):
if request.method == 'POST':
try:
dev = Device.objects.get(agent_id=request.POST['agent_id'])
return render(request, 'courses/deviceconfirmation.html', {'dev': dev})
except Device.DoesNotExist:
return HttpResponseRedirect('invalidimp')
else:
raise Http404('Only POSTs are allowed')
urls.py:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.homepage, name='homepage'),
url(r'contact/$', views.contact, name='contact'),
url(r'login/$', views.login, name='login'),
url(r'products/$', views.products, name='products'),
url(r'register/$', views.register, name='register'),
url(r'register/thanks/$', views.thanks, name='thanks'),
url(r'register/inuse/$', views.inuse, name='inuse'),
url(r'login/accountinfo/$', views.accountinfo, name='accountinfo'),
url(r'devices/$', views.devices, name='devices'),
url(r'devices/deviceconfirmation/$', views.deviceconfirmation, name='deviceconfirmation'),
url(r'devices/deviceconfirmation/invalidimp/$', views.invalidimp, name='invalidimp'),
]
当登录用户仅向自己添加设备时:您可以在post时将当前用户作为所有者传递给表单。如果不是 posting,您最初不需要表单中的所有者。在表单中,覆盖保存方法并在保存设备实例之前传递所有者。
--
更新 根据评论:
- 修改为url用于设备确认和查看; url 现在接受设备 ID。请参阅下面的代码更新
- 另请参阅模板更新信息
查看(假设 def 设备用于 get 和 post):
def devices(request):
if request.method == 'POST":
devform = DeviceForm(request.POST, owner=request.user)
if devform.is_valid():
dev = devform.save()
return HttpResponseRedirect(reverse('deviceconfirmation', kwargs={'device_id': dev.id}))
else:
return render_to_response('courses/devices.html', {'devform': devform}, context_instance=RequestContext(request))
else:
devform = DeviceForm()
return render_to_response('courses/devices.html', {'devform': devform}, context_instance=RequestContext(request))
查看设备确认:
def deviceconfirmation(request, device_id=None):
try:
dev = Device.objects.get(id=device_id)
return render(request, 'courses/deviceconfirmation.html', {'dev': dev})
except Device.DoesNotExist:
return HttpResponseRedirect('invalidimp')
表格:
class DeviceForm(ModelForm):
class Meta:
model = Device
fields = ['name', 'agent_id', 'device_type']
def __init__(self, *args, **kwargs):
owner = kwargs.pop('owner', None)
super(DeviceForm, self).__init__(*args, **kwargs)
self.owner = owner;
def clean_agent_id(self):
agent_id = self.cleaned_data['agent_id']
if Device.objects.filter(agent_id=agent_id).exists():
raise forms.ValidationError(u'agent_id "%s" is already in use.' % agent_id)
return agent_id
def save(self, commit=True):
device = super(DeviceForm, self).save(commit=False)
device.owner = self.owner
if commit:
device.save()
return device
模板:
- 删除模板中的表单操作 url -> 当您 post 时,它将转到您执行获取的同一视图(即
devices
视图); <form action="" .....>
- 删除所有者表单字段 - 显示当前所有者用户名,只需使用
{{request.user.username}}
URL:
url(r'devices/deviceconfirmation/(?P<device_id>\S+)/$', views.deviceconfirmation, name='deviceconfirmation'),
基本上,我正在尝试为我的网站提供一项功能,让人们可以在他们的用户帐户中注册一个电子小鬼(多个)。我的问题是我的 Device 模型,通过扩展我的 DeviceForm ModelForm 使用 ForeignKey 来引用用户对象。因此,当我去注册一个设备时,它会询问设备的名称、imp 的 agent_id、设备类型和与帐户关联的用户。我认为我的 is_valid() 验证失败的地方在于我如何引用用户模型。我不认为它是用户对象的 "valid" 输入。是否有其他方法可以使用用户的用户名 link 将设备连接到正确的帐户?
Models.py:
class Device(models.Model):
name = models.CharField(max_length=100)
agent_id = models.CharField(max_length=100)
device_type = models.CharField(max_length=100, choices=(
("imp", "Electric Imp P3V3"),
))
owner = models.ForeignKey(User)
def __unicode__(self):
return self.name
class DeviceForm(ModelForm):
class Meta:
model = Device
fields = ['name', 'agent_id', 'device_type', 'owner']
def clean_agent_id(self):
agent_id = self.cleaned_data['agent_id']
if Device.objects.exclude(pk=self.instance.pk).filter(agent_id=agent_id).exists():
raise forms.ValidationError(u'agent_id "%s" is already in use.' % agent_id)
return agent_id
Views.py:
def devices(request):
devform = DeviceForm(request.POST)
if devform.is_valid():
device_obj = devform.save()
device_obj.save()
return HttpResponseRedirect('deviceconfirmation')
else:
devform = DeviceForm()
return render_to_response('courses/devices.html', {'devform': devform}, context_instance=RequestContext(request))
devices.html:
{% extends "layout.html" %}
{% load static from staticfiles %}
{% block title %}{{ page.title }}{% endblock %}
{% block content %}
<article>
<div id="wrapper">
<p id="devicecreate">Register your device to your account:</p>
<form action="{% url 'courses:deviceconfirmation' %}" id="devform" method="post"> {% csrf_token %}
<p>
<label for="name">Device Name:</label>
<input id="name" name="name" type="text">
</p>
<p>
<label for="agent_id">Agent ID:</label>
<input id="agent_id" name="agent_id" type="text">
</p>
<p>
<label for="device_type">Imp Type:</label>
<select name="device_type" form="devform" id="selectbox">
<option value="imp">Imp Regular</option>
<option value="Electric Imp P3V3">Imp P3V3</option>
</select>
</p>
<p>
<label for="owner">Device Owner(username):</label>
<input id="owner" name="owner" type="text">
</p>
<p>
<input type="submit" value="REGISTER DEVICE" id="submit">
</p>
</form>
</div>
</article>
{% endblock %}
views.py 设备确认:
def deviceconfirmation(request):
if request.method == 'POST':
try:
dev = Device.objects.get(agent_id=request.POST['agent_id'])
return render(request, 'courses/deviceconfirmation.html', {'dev': dev})
except Device.DoesNotExist:
return HttpResponseRedirect('invalidimp')
else:
raise Http404('Only POSTs are allowed')
urls.py:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.homepage, name='homepage'),
url(r'contact/$', views.contact, name='contact'),
url(r'login/$', views.login, name='login'),
url(r'products/$', views.products, name='products'),
url(r'register/$', views.register, name='register'),
url(r'register/thanks/$', views.thanks, name='thanks'),
url(r'register/inuse/$', views.inuse, name='inuse'),
url(r'login/accountinfo/$', views.accountinfo, name='accountinfo'),
url(r'devices/$', views.devices, name='devices'),
url(r'devices/deviceconfirmation/$', views.deviceconfirmation, name='deviceconfirmation'),
url(r'devices/deviceconfirmation/invalidimp/$', views.invalidimp, name='invalidimp'),
]
当登录用户仅向自己添加设备时:您可以在post时将当前用户作为所有者传递给表单。如果不是 posting,您最初不需要表单中的所有者。在表单中,覆盖保存方法并在保存设备实例之前传递所有者。
--
更新 根据评论:
- 修改为url用于设备确认和查看; url 现在接受设备 ID。请参阅下面的代码更新
- 另请参阅模板更新信息
查看(假设 def 设备用于 get 和 post):
def devices(request):
if request.method == 'POST":
devform = DeviceForm(request.POST, owner=request.user)
if devform.is_valid():
dev = devform.save()
return HttpResponseRedirect(reverse('deviceconfirmation', kwargs={'device_id': dev.id}))
else:
return render_to_response('courses/devices.html', {'devform': devform}, context_instance=RequestContext(request))
else:
devform = DeviceForm()
return render_to_response('courses/devices.html', {'devform': devform}, context_instance=RequestContext(request))
查看设备确认:
def deviceconfirmation(request, device_id=None):
try:
dev = Device.objects.get(id=device_id)
return render(request, 'courses/deviceconfirmation.html', {'dev': dev})
except Device.DoesNotExist:
return HttpResponseRedirect('invalidimp')
表格:
class DeviceForm(ModelForm):
class Meta:
model = Device
fields = ['name', 'agent_id', 'device_type']
def __init__(self, *args, **kwargs):
owner = kwargs.pop('owner', None)
super(DeviceForm, self).__init__(*args, **kwargs)
self.owner = owner;
def clean_agent_id(self):
agent_id = self.cleaned_data['agent_id']
if Device.objects.filter(agent_id=agent_id).exists():
raise forms.ValidationError(u'agent_id "%s" is already in use.' % agent_id)
return agent_id
def save(self, commit=True):
device = super(DeviceForm, self).save(commit=False)
device.owner = self.owner
if commit:
device.save()
return device
模板:
- 删除模板中的表单操作 url -> 当您 post 时,它将转到您执行获取的同一视图(即
devices
视图);<form action="" .....>
- 删除所有者表单字段 - 显示当前所有者用户名,只需使用
{{request.user.username}}
URL:
url(r'devices/deviceconfirmation/(?P<device_id>\S+)/$', views.deviceconfirmation, name='deviceconfirmation'),