下午好,我是Django的新手,我不确定该怎么做。我有一个使用以下模型的Django 2.2项目:
class Equipment(models.Model):
name = models.CharField(
max_length=15,
unique=True,
verbose_name='asset name')
asset_cat = models.ForeignKey('category',on_delete=models.PROTECT,verbose_name='asset category')
asset_loc = models.ForeignKey('location',on_delete=models.PROTECT,verbose_name='asset location')
state = models.ForeignKey('status',on_delete=models.PROTECT,verbose_name='status')
brand = models.CharField(
max_length=15,
unique=False,
blank=True)
model = models.CharField(
max_length=12,
unique=False,
blank=True,
verbose_name='model number')
def __str__(self):
return "{}".format(self.name)
def get_absolute_url(self):
return reverse('equipment-detail', args=[str(self.id)])
class Meta:
ordering = ['asset_cat', 'name']
verbose_name_plural = 'pieces of equipment'
class Action(models.Model):
name = models.ForeignKey('equipment',on_delete=models.PROTECT,verbose_name='asset name',blank=False)
dt = models.DateTimeField(
auto_now_add=True,
verbose_name='date and time of incident')
incident = models.TextField(
blank=True,
null=True)
CHANGE = 'CHANGE'
SERVICE = 'SERVICE'
ACTION_CHOICES = (
(CHANGE, 'CHANGE'),
(SERVICE, 'SERVICE')
)
act = models.TextField(
blank=True,
choices=ACTION_CHOICES,
null=True,
verbose_name='action taken')
act_detail = models.TextField(
verbose_name='action detail',
blank=False)
result = models.TextField(
blank=True,
null=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('service-detail', args=[str(self.id)])
class Meta:
ordering = ['-dt']
verbose_name_plural = 'service calls'
我有这样的设备详细视图:
class EquipmentDetailView(generic.DetailView):
model = Equipment
template_name = 'equipment_detail.html'
def get_context_data(self, **kwargs):
context = super(EquipmentDetailView, self).get_context_data(**kwargs)
return context
详细信息视图有两个按钮:编辑和服务。如果单击“编辑”,我将拥有一个模型表单,该模型表单使我可以成功地编辑“设备”模型的该实例。
但是,当我单击服务按钮时,我的表单出现以创建Action模型的实例,但是当我提交该表单时,它告诉我name_id中的null值违反了not null约束。
看来我的问题是,如何将Equipment.id从“设备详细信息”视图传递到action.form创建表单的action.name并保留服务按钮的概念?
操作表格:
class ServiceForm(forms.ModelForm):
class Meta:
model = Action
fields = ['incident', 'act_detail', 'result']
操作(实际上是服务)视图:
class EquipmentServiceView(generic.CreateView):
template_name = 'equipment_service.html'
form_class = ServiceForm
queryset = Action.objects.all()
答案 0 :(得分:0)
假设您不想采用最简单的解决方案在表单字段中包含name
并将url设置为:
/equipment/<id>
-设备详细信息视图
/service
-服务(或操作)创建视图
有几种传递设备ID的方式:
1)来自网址
我们将更改url以接受equipment_id。这意味着您将拥有网址/service
而不是/equipment/<equipment_id>/service
。
可能是最好的解决方案-您将根据REST体系结构使用URL,并且结构非常清晰。客户端可以从任何地方访问页面(就像从邮件中复制粘贴链接一样),它将起作用。
urls.py:
urlpatterns = [
path('equipment/<int:pk>', EquipmentDetailView.as_view(), name='equipment-detail'),
path('equipment/<int:equipment_pk>/service', EquipmentServiceView.as_view(), name='service-create')
]
您的服务按钮应如下所示:<a href="{% url 'service-create' object.pk %}">service</a>
最后是您的看法:
class EquipmentServiceView(CreateView):
template_name = 'equipment_service.html'
form_class = ServiceForm
queryset = Action.objects.all()
def form_valid(self, form):
equipment_pk = self.kwargs['equipment_pk']
equipment = get_object_or_404(Equipment, pk=equipment_pk)
self.object = form.save(commit=False)
self.object.name = equipment
self.object.save()
return super().form_valid(form)
2)会话数据
如果您想保留服务URL而无需添加equipment_id,则可以将设备ID存储在session数据中(在服务器上)或cookie中(在客户端上)。这不是很好-客户必须在创建EquipmentDetailView
之前先进入Service
,但这将使您的URL保持完整。
views.py:
class EquipmentDetailView(DetailView):
model = Equipment
template_name = 'equipment_detail.html'
def get(self, request, *args, **kwargs):
response = super().get(request, *args, **kwargs)
request.session['last_equipment_pk'] = self.object.pk
return response
class EquipmentServiceView(CreateView):
template_name = 'equipment_service.html'
form_class = ServiceForm
queryset = Action.objects.all()
def form_valid(self, form):
equipment_pk = self.request.session.get('last_equipment_pk')
equipment = get_object_or_404(Equipment, pk=equipment_pk)
self.object = form.save(commit=False)
self.object.name = equipment
self.object.save()
return super().form_valid(form)
P.S。:name
是ForeignField
的错误字段名-应该类似于equipment
之类。这些标签通常与CharField
关联,并且应该是字符串。