如何编写代码,以便在使用 django 的模型中只选择一个单选按钮。?
How to write code such that only one of the radio button should be selected in models with django.?
#models.py
from django.db import models
from django.contrib.auth.models import User
CHOICES = (('1','Earned Leave'),('2','Casual Leave'),('3','Sick Leave'),('4','Paid Leave'))
class Leave(models.Model):
employee_ID = models.CharField(max_length = 20)
name = models.CharField(max_length = 50)
user = models.ForeignKey(User, on_delete = models.CASCADE, null =True)
department = models.CharField(max_length = 50)
designation = models.CharField(max_length = 50)
type_of_leave = models.CharField(max_length = 15, choices = CHOICES)
from_date = models.DateField(help_text = 'mm/dd/yy')
to_date = models.DateField(help_text = 'mm/dd/yy')
reporting_manager = models.CharField(max_length = 50, default = None, help_text = '0001_manager, 0002_manager')
reason = models.CharField(max_length= 180)
accepted = models.BooleanField(('accept'), default= False)
rejected = models.BooleanField(('reject'), default = False)
reason_reject = models.CharField(('reason for rejection'),max_length=50) // this didn't help me.
def __str__(self):
return self.name
这是一个休假申请表,其中只有两个字段 (accepted, rejected
) 应该被选中,如果拒绝字段没有被选中,那么 reason_reject
不应显示在/admin
面板。
#forms.py
from django import forms
from lrequests import models
class LeaveRequestForm(forms.ModelForm):
class Meta:
fields = ("name", "employee_ID", "department", "designation", "type_of_leave", "from_date", "to_date", "reporting_manager", "reason")
model = models.Leave
用户填写表格并提交。所以,现在管理员必须接受或拒绝它。只有在管理员选择 rejected
字段后,reason_reject
字段才会出现在管理员面前。这一切应该只发生在管理员端。
#admin.py
from django.contrib import admin
from . import models
@admin.register(models.Leave)
class LeaveAdmin(admin.ModelAdmin):
list_display = ["name"]
#"employee_ID", "department", "designation", "type_of_leave", "from_date", "to_date", "reporting_manager", "reason", "accepted", "rejected", "reason_reject"
list_filter = ['department','type_of_leave']
def get_queryset(self, request):
qs = super().get_queryset(request)
if request.user.is_superuser:
return qs
return (qs.filter(reporting_manager=request.user.username) or qs.filter(employee_ID=request.user.username))
# def get_readonly_fields(self, request, obj=None):
# # the logged in user can be accessed through the request object
# if obj and request.user.is_staff:
# readonly_fields = [f.name for f in self.opts.fields]
# readonly_fields.remove('accepted')
# readonly_fields.remove('rejected')
# return readonly_fields
#the above chunk of get_readonly_fields was written so that the admin could only either 'accept' or 'reject' the form.
def get_fields(self, request, obj=None):
fields = [f.name for f in self.opts.fields]
if obj and obj.rejected:
fields.append('reason_reject')
return fields
通过运行上面的代码我得到
KeyError at /admin/lrequests/leave/15/change/
和
"Key 'id' not found in 'LeaveForm'. Choices are: accepted, department, designation, employee_ID, from_date, name, reason, reason_reject, rejected, reporting_manager, to_date, type_of_leave, user."
整个前提都是有缺陷的。你不能在模型 definition 中执行这种逻辑,因为那时没有实例,所以没有值可以比较。即使可以,它仍然没有意义,因为模型定义定义了模型具有的数据库列;你不能让不同的实例在数据库中有不同的列。模型定义适用于 整个 模型。您需要在 class 定义中包含 reason_reject
。
您可能想要根据模型中的值更改表单。您可以通过覆盖 get_fields
方法在管理员中执行此操作。
class LeaveAdmin(admin.ModelAdmin):
...
def get_fields(self, request, obj=None):
fields = [....list of fields for the form...]
if obj and obj.rejected:
fields.append('reason_reject')
return fields
请注意,您可能需要考虑是否真的需要单独的 accepted/rejected 字段;最好为申请状态设置一个字段:接受或拒绝。您可以将它们表示为单独的单选按钮或下拉菜单。
STATUS_CHOICES = (
(1, 'Accepted'),
(0, 'Rejected'),
)
status = models.IntegerField(choices=STATUS_CHOICES, blank=True, null=True)
首先,将其定义为下拉菜单。那就是像
这样的选择
STATUS_CHOICES = (('0', 'Rejected'),('1', 'Accepted'),)
class Leave(models.Model):
...
status = models.CharField(max_length = 15, choices = STATUS_CHOICES)
然后在admin.py
class LeaveAdmin(admin.ModelAdmin):
...
radio_fields = {"status": admin.HORIZONTAL}
#models.py
from django.db import models
from django.contrib.auth.models import User
CHOICES = (('1','Earned Leave'),('2','Casual Leave'),('3','Sick Leave'),('4','Paid Leave'))
class Leave(models.Model):
employee_ID = models.CharField(max_length = 20)
name = models.CharField(max_length = 50)
user = models.ForeignKey(User, on_delete = models.CASCADE, null =True)
department = models.CharField(max_length = 50)
designation = models.CharField(max_length = 50)
type_of_leave = models.CharField(max_length = 15, choices = CHOICES)
from_date = models.DateField(help_text = 'mm/dd/yy')
to_date = models.DateField(help_text = 'mm/dd/yy')
reporting_manager = models.CharField(max_length = 50, default = None, help_text = '0001_manager, 0002_manager')
reason = models.CharField(max_length= 180)
accepted = models.BooleanField(('accept'), default= False)
rejected = models.BooleanField(('reject'), default = False)
reason_reject = models.CharField(('reason for rejection'),max_length=50) // this didn't help me.
def __str__(self):
return self.name
这是一个休假申请表,其中只有两个字段 (accepted, rejected
) 应该被选中,如果拒绝字段没有被选中,那么 reason_reject
不应显示在/admin
面板。
#forms.py
from django import forms
from lrequests import models
class LeaveRequestForm(forms.ModelForm):
class Meta:
fields = ("name", "employee_ID", "department", "designation", "type_of_leave", "from_date", "to_date", "reporting_manager", "reason")
model = models.Leave
用户填写表格并提交。所以,现在管理员必须接受或拒绝它。只有在管理员选择 rejected
字段后,reason_reject
字段才会出现在管理员面前。这一切应该只发生在管理员端。
#admin.py
from django.contrib import admin
from . import models
@admin.register(models.Leave)
class LeaveAdmin(admin.ModelAdmin):
list_display = ["name"]
#"employee_ID", "department", "designation", "type_of_leave", "from_date", "to_date", "reporting_manager", "reason", "accepted", "rejected", "reason_reject"
list_filter = ['department','type_of_leave']
def get_queryset(self, request):
qs = super().get_queryset(request)
if request.user.is_superuser:
return qs
return (qs.filter(reporting_manager=request.user.username) or qs.filter(employee_ID=request.user.username))
# def get_readonly_fields(self, request, obj=None):
# # the logged in user can be accessed through the request object
# if obj and request.user.is_staff:
# readonly_fields = [f.name for f in self.opts.fields]
# readonly_fields.remove('accepted')
# readonly_fields.remove('rejected')
# return readonly_fields
#the above chunk of get_readonly_fields was written so that the admin could only either 'accept' or 'reject' the form.
def get_fields(self, request, obj=None):
fields = [f.name for f in self.opts.fields]
if obj and obj.rejected:
fields.append('reason_reject')
return fields
通过运行上面的代码我得到
KeyError at /admin/lrequests/leave/15/change/
和
"Key 'id' not found in 'LeaveForm'. Choices are: accepted, department, designation, employee_ID, from_date, name, reason, reason_reject, rejected, reporting_manager, to_date, type_of_leave, user."
整个前提都是有缺陷的。你不能在模型 definition 中执行这种逻辑,因为那时没有实例,所以没有值可以比较。即使可以,它仍然没有意义,因为模型定义定义了模型具有的数据库列;你不能让不同的实例在数据库中有不同的列。模型定义适用于 整个 模型。您需要在 class 定义中包含 reason_reject
。
您可能想要根据模型中的值更改表单。您可以通过覆盖 get_fields
方法在管理员中执行此操作。
class LeaveAdmin(admin.ModelAdmin):
...
def get_fields(self, request, obj=None):
fields = [....list of fields for the form...]
if obj and obj.rejected:
fields.append('reason_reject')
return fields
请注意,您可能需要考虑是否真的需要单独的 accepted/rejected 字段;最好为申请状态设置一个字段:接受或拒绝。您可以将它们表示为单独的单选按钮或下拉菜单。
STATUS_CHOICES = (
(1, 'Accepted'),
(0, 'Rejected'),
)
status = models.IntegerField(choices=STATUS_CHOICES, blank=True, null=True)
首先,将其定义为下拉菜单。那就是像
这样的选择STATUS_CHOICES = (('0', 'Rejected'),('1', 'Accepted'),)
class Leave(models.Model):
...
status = models.CharField(max_length = 15, choices = STATUS_CHOICES)
然后在admin.py
class LeaveAdmin(admin.ModelAdmin):
...
radio_fields = {"status": admin.HORIZONTAL}