django admin fieldsets - 添加相关模型的字段 [英] django admin fieldsets - adding fields of related models
问题描述
我有一个与 User
的OneToOne关系的模型 Employee
。我正在尝试在员工管理员中添加一些用户字段( first_name,last_name,username,email
),以便直接从员工添加/更改窗体中编辑这些字段,但我还没有想出如何做到这一点。
我看到另一个时间以类似的方式做这种事情,但现在我有一个字段集错误:
为Employee指定的未知字段(first_name)。检查类EmployeeAdmin的字段/ fieldsets / exclude属性
这里是代码:
#FIELDSETS
default_employee_fieldset =(
('General',{
'fields':(
('user','full_name' ,),
),
}),
#..OTHER字段不包括
)
finance_fields_employee_fieldset = [
',{
'fields':(
('full_name',),
('first_name','last_name')
),
}),
#..没有包含
#ADMIN FORM
class EmployeeAdminForm(forms.ModelForm):
class Meta:
model = Employee
def __init __(self,* args,** kwargs):
super(EmployeeAdminForm,self).__ init __(* args,** kwargs )
self.fields ['first_name'] = forms.CharField(_('first name') ,max_length = 30,blank = True)
self.fields ['last_name'] = forms.CharField(_('last name'),max_length = 30,blank = True)
如果在kwargs中的instance:
user = kwargs ['instance']。user
self.fields ['first_name']。initial = user.first_name
self.fields ['last_name' ] .initial = user.last_name
#MODEL ADMIN
class EmployeeAdmin(ExtendedAdmin):
list_display =('user','department' ,'line_manager','act_line_manager','jobtitle','office','payroll_id')
search_fields =('user__username','user__first_name','user__last_name',
'line_manager__user__first_name' line_manager__user__last_name')
list_filter =('department','grade','clearance','office','user__is_active','user__is_staff',
'ready_for_paid_work')
dsets = default_employee_fieldset
def changelist_view(self,request,extra_context = None):
extra_context = {'title':'Employee details'}
return super(EmployeeAdmin,self) 。$。$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $
def change_view(self,request,object_id,form_url ='',extra_context = b record = Employee.objects.get(id = object_id)
extra_context = {'title':'编辑员工记录:%s'%(str(record),)}
except(ValueError,Employee .DoesNotExist):
pass
#生成一个新的CSRF令牌,因为这个页面包含敏感数据
rotate_token(request)
return super(EmployeeAdmin,self).change_view(request,object_id ,form_url,extra_context)
def queryset(self,request):
qs = super(EmployeeAdmin,self).queryset(request)
如果reque st.user.is_superuser:
return qs
elif request.user.has_perm('myapp.change_all_employees'):
如果request.user.has_perm('myapp.change_ex_employees'):
return qs.filter(user__is_staff = True)
else:
return qs.filter(user__is_staff = True,user__is_active = True)
else:
返回qs.filter(user__is_staff = True,user__is_active = True).filter(
Q(line_manager = request.user.employee)|
Q(acting_line_manager = request.user.employee)|
Q(user = request.user)
)
def get_form(self,request,obj =无,* args,** kwargs):
self。 form = EmployeeAdminForm
如果obj:
如果request.user.has_perm('myapp.change_hr_employee_data'):
self.readonly_fields =('user',)
self.exclude =无
self.fieldsets = finance_fields_employee_fieldset
elif request.user.has_perm('myapp.change_employee_data_operations'):
if request.user == obj.user:
#set readonly fields
self.exclude = None
self.fieldsets = finance_fields_employee_fieldset
else:
#set readonly fields
self.exclude =('employer_pension_contribution','employee_pension_contribution')
self.fieldsets = default_emplo yee_fieldset
else:
#如果用户在AAA部门,而不是员工的linemanager,而不是自己的记录
如果request.user.employee.department == settings.DPTS ['AAA']
如果request.user == obj.user:
#set readonly fields
else:
#set readonly fields
self.exclude =('account_number','sort_code' ,'salary',
'employer_pension_contribution','employee_pension_contribution',)
self.fieldsets = default_employee_fieldset
else:
#如果用户正在编辑自己的记录
if request.user == obj.user:
#set readonly fields
self.exclude =('account_reference','payroll_id',)
self.fieldsets = finance_fields_employee_fieldset [0:-2]
#如果用户正在编辑一些为线路管理员
else:
如果request.user.employee == obj.line_manager或\
request.user.employee == obj.acting_line_manager:
#set readonly fields
self.fieldsets = default_employee_fieldset
self.exclude =('employer_pension_contribution','employee_pension_contribution')
else:
self.readonly_fields =()
self.exclude =()
self.fieldsets = default_employee_fieldset
form = super(EmployeeAdmin,self).get_form(请求,* args,** kwargs)
form.request = request
return form
def save_model(self,request,obj,form ,更改):
如果更改:
old_obj = Employee.objects.get(id = obj.id)
if obj.jobtitle!= old_obj.jobtitle:
employee_detail_change_notification(obj,'job title',obj。 jobtitle.name)
如果obj.line_manager!= old_obj.line_manager:
employee_detail_change_notification(obj,'line manager',obj.line_manager)
如果obj.acting_line_manager!= old_obj.acting_line_manager:
employee_detail_change_notification(obj,'act line manager',obj.acting_line_manager)
如果obj.home_address_line1!= old_obj.home_address_line1或\
obj.home_address_line2!= old_obj.home_address_line2或\
obj.home_address_line3!= old_obj.home_address_line3或\
obj.home_address_city!= old_obj.home_address_city或\
obj.home_address_postcode!= old_obj.home_address_postcode或\
obj.home_address_country!= old_obj.home_address_country or\
obj.home_address_phone!= old_obj.home_address_phone or\
obj.personal_email!= old_obj.personal_email:
new_address ='%s\\ \\ n%s\\\
%s\\\
%s\\\
%s\\\
%s\\\
\\\
Phone:%s\\\
Email:%s'%(
obj.home_address_line1,
obj.home_address_line2,
obj.home_address_line3,
obj.home_address_city,
obj.home_address_postcode,
obj.get_home_address_country_display(),
obj.home_address_phone,
obj.personal_email,
)
employee_detail_change_notification(obj,'home address details',new_address)
如果obj.marital_status!= old_obj.marital_status:
employee_detail_cha nge_notification(obj,'marital_status',obj.get_marital_status_display())
obj.save()
admin.site.register(Employee,EmployeeAdmin)
有任何帮助?
管理员找不到user_name的原因是在类级别上没有在您的自定义表单上定义user_name字段。它仅在 __ init __
中定义。当管理员检查可用字段的表单时,它只能访问类,而不是初始化的表单。所以检查表单类不会显示user_name可用。
直接在类级别定义所有字段,而不是窗体的 __ init __
方法。如果您不需要所有情况的所有字段,则根据需要从 __ init __
方法中的表单的字段字典中根据需要删除字段。
您也可以按照相反的方向执行此操作 - 将员工信息添加到用户编辑页面?这可以按照 https ://docs.djangoproject.com/en/1.4/topics/auth/#adding-userprofile-fields-to-the-admin 。
最后,似乎你正在到达可能更容易实现所需功能的阶段,而不使用管理员 - 而Django的管理员确实有很多可扩展性功能,在某些时候编写自己的实现将比使用Admin更容易。 p>
I have a model Employee
with a OneToOne relationship with User
. I'm trying to include in the Employee admin some User fields (first_name, last_name, username, email
), in order to edit those fields directly from the Employee Add/Change form, but I still haven't figured out how to do it.
I see another time do this kind of thing in a similar way, but now I have a fieldset error:
Unknown field(s) (first_name) specified for Employee. Check fields/fieldsets/exclude attributes of class EmployeeAdmin
here's the code:
# FIELDSETS
default_employee_fieldset = (
('General', {
'fields': (
('user', 'full_name',),
),
}),
# ..OTHER FIELDS NOT INCLUDED
)
finance_fields_employee_fieldset = [
('General', {
'fields': (
('full_name',),
('first_name', 'last_name')
),
}),
# ..OTHER FIELDS NOT INCLUDED
]
# ADMIN FORM
class EmployeeAdminForm(forms.ModelForm):
class Meta:
model = Employee
def __init__(self, *args, **kwargs):
super(EmployeeAdminForm, self).__init__(*args, **kwargs)
self.fields['first_name'] = forms.CharField(_('first name'), max_length=30, blank=True)
self.fields['last_name'] = forms.CharField(_('last name'), max_length=30, blank=True)
if 'instance' in kwargs:
user = kwargs['instance'].user
self.fields['first_name'].initial = user.first_name
self.fields['last_name'].initial = user.last_name
# MODEL ADMIN
class EmployeeAdmin(ExtendedAdmin):
list_display = ('user', 'department', 'line_manager', 'acting_line_manager', 'jobtitle', 'office', 'payroll_id',)
search_fields = ('user__username', 'user__first_name', 'user__last_name',
'line_manager__user__first_name', 'line_manager__user__last_name')
list_filter = ('department', 'grade', 'clearance', 'office', 'user__is_active', 'user__is_staff',
'ready_for_paid_work')
fieldsets = default_employee_fieldset
def changelist_view(self, request, extra_context=None):
extra_context = {'title': 'Employee details'}
return super(EmployeeAdmin, self).changelist_view(request, extra_context)
def change_view(self, request, object_id, form_url='', extra_context=None):
if object_id:
try:
record = Employee.objects.get(id=object_id)
extra_context = {'title': 'Edit employee record: %s' % (str(record),)}
except (ValueError, Employee.DoesNotExist):
pass
# Generate a new CSRF token as this page contains sensitive data
rotate_token(request)
return super(EmployeeAdmin, self).change_view(request, object_id, form_url, extra_context)
def queryset(self, request):
qs = super(EmployeeAdmin, self).queryset(request)
if request.user.is_superuser:
return qs
elif request.user.has_perm('myapp.change_all_employees'):
if request.user.has_perm('myapp.change_ex_employees'):
return qs.filter(user__is_staff=True)
else:
return qs.filter(user__is_staff=True, user__is_active=True)
else:
return qs.filter(user__is_staff=True, user__is_active=True).filter(
Q(line_manager=request.user.employee) |
Q(acting_line_manager=request.user.employee) |
Q(user=request.user)
)
def get_form(self, request, obj=None, *args, **kwargs):
self.form = EmployeeAdminForm
if obj:
if request.user.has_perm('myapp.change_hr_employee_data'):
self.readonly_fields = ('user', )
self.exclude = None
self.fieldsets = finance_fields_employee_fieldset
elif request.user.has_perm('myapp.change_employee_data_operations'):
if request.user == obj.user:
# set readonly fields
self.exclude = None
self.fieldsets = finance_fields_employee_fieldset
else:
# set readonly fields
self.exclude = ('employer_pension_contribution', 'employee_pension_contribution',)
self.fieldsets = default_employee_fieldset
else:
# if user is in AAA department and not employee's linemanager and not own record
if request.user.employee.department == settings.DPTS['AAA']
if request.user == obj.user:
# set readonly fields
else:
# set readonly fields
self.exclude = ('account_number', 'sort_code', 'salary',
'employer_pension_contribution', 'employee_pension_contribution',)
self.fieldsets = default_employee_fieldset
else:
# if user is editing his own record
if request.user == obj.user:
# set readonly fields
self.exclude = ('account_reference', 'payroll_id',)
self.fieldsets = finance_fields_employee_fieldset[0:-2]
# if user is editing some for whom is line manager
else:
if request.user.employee == obj.line_manager or \
request.user.employee == obj.acting_line_manager:
# set readonly fields
self.fieldsets = default_employee_fieldset
self.exclude = ('employer_pension_contribution', 'employee_pension_contribution',)
else:
self.readonly_fields = ()
self.exclude = ()
self.fieldsets = default_employee_fieldset
form = super(EmployeeAdmin, self).get_form(request, *args, **kwargs)
form.request = request
return form
def save_model(self, request, obj, form, change):
if change:
old_obj = Employee.objects.get(id=obj.id)
if obj.jobtitle != old_obj.jobtitle:
employee_detail_change_notification(obj, 'job title', obj.jobtitle.name)
if obj.line_manager != old_obj.line_manager:
employee_detail_change_notification(obj, 'line manager', obj.line_manager)
if obj.acting_line_manager != old_obj.acting_line_manager:
employee_detail_change_notification(obj, 'acting line manager', obj.acting_line_manager)
if obj.home_address_line1 != old_obj.home_address_line1 or \
obj.home_address_line2 != old_obj.home_address_line2 or\
obj.home_address_line3 != old_obj.home_address_line3 or\
obj.home_address_city != old_obj.home_address_city or\
obj.home_address_postcode != old_obj.home_address_postcode or\
obj.home_address_country != old_obj.home_address_country or\
obj.home_address_phone != old_obj.home_address_phone or\
obj.personal_email != old_obj.personal_email:
new_address = '%s\n%s\n%s\n%s\n%s\n%s\n\nPhone: %s\nEmail: %s' %(
obj.home_address_line1,
obj.home_address_line2,
obj.home_address_line3,
obj.home_address_city,
obj.home_address_postcode,
obj.get_home_address_country_display(),
obj.home_address_phone,
obj.personal_email,
)
employee_detail_change_notification(obj, 'home address details', new_address)
if obj.marital_status != old_obj.marital_status:
employee_detail_change_notification(obj, 'marital_status', obj.get_marital_status_display())
obj.save()
admin.site.register(Employee, EmployeeAdmin)
Any help on this?
The reason Admin doesn't find user_name is that the user_name field isn't defined on your custom form at class level. It is only defined in __init__
. When the admin inspects the form for available fields it has access only to the class, not an initialized form. So inspecting the form class doesn't show that user_name is available.
Define all the fields directly on class level instead of the form's __init__
method. If you don't need all the fields for all cases, then delete fields as needed from the form's fields dictionary in the __init__
method as needed.
You could maybe also do this in the reverse direction - adding Employee information to User edit page? This can be done as documented in https://docs.djangoproject.com/en/1.4/topics/auth/#adding-userprofile-fields-to-the-admin.
Finally, it seems you are reaching the stage where it might be easier to implement the features you want without using Admin - while Django's Admin does have a lot of extensibility features, at some point writing your own implementation will be easier than using Admin.
这篇关于django admin fieldsets - 添加相关模型的字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!