2009-03-26 35 views
12

Tôi đã thử nhiều phương pháp khác nhau để đạt được điều này.Django - Ghi đè get_form để tùy chỉnh biểu mẫu quản trị dựa trên yêu cầu

Tôi quyết định không ghi đè formfield_for_dbfield vì nó không nhận được bản sao của đối tượng yêu cầu và tôi hy vọng tránh được việc hack thread_locals.

tôi định cư trên trọng get_form trong lớp ModelAdmin của tôi và thử như sau:

class PageOptions(admin.ModelAdmin): 
    def get_form(self, request, obj=None, **kwargs): 
     if request.user.is_superuser: 
      self.fieldsets = ((None, {'fields': ('title','name',),}),) 
     else: 
      self.fieldsets = ((None, {'fields': ('title',),}),) 
     return super(PageOptions,self).get_form(request, obj=None, **kwargs) 

Khi tôi in fieldsets hoặc declared_fieldsets từ bên trong get_form tôi nhận None (hoặc bất cứ điều gì tôi thiết lập như là một giá trị ban đầu trong PageOptions).

Tại sao tính năng này không hoạt động và có cách nào tốt hơn để thực hiện việc này?

+1

Bạn đã cố gắng khai báo một fieldset ở đâu đó trong lớp PageOptions chỉ để xem nó có hoạt động không? –

+0

Yep, Chương trình đó không có vấn đề gì trong get_form –

Trả lời

8

Tôi không có ý tưởng tại sao in tài sản không cung cấp cho bạn muốn, bạn chỉ được phân công (tôi đoán có thể là phụ thuộc vào nơi bạn in, chính xác), nhưng cố gắng trọng get_fieldsets thay thế. Việc thực hiện cơ sở trông như thế này:

def get_fieldsets(self, request, obj=None): 
    if self.declared_fieldsets: 
     return self.declared_fieldsets 
    form = self.get_formset(request).form 
    return [(None, {'fields': form.base_fields.keys()})] 

Tức là bạn sẽ có thể trả lại các bộ dữ liệu của mình.

CHỈNH SỬA bởi andybak. 4 năm sau và tôi lại tìm thấy câu hỏi của riêng mình khi cố gắng làm điều tương tự trên một dự án khác. Lần này tôi đã đi với cách tiếp cận này mặc dù chút thay đổi để tránh việc phải lặp lại fieldsets định nghĩa:

def get_fieldsets(self, request, obj=None): 
    # Add 'item_type' on add forms and remove it on changeforms. 
    fieldsets = super(ItemAdmin, self).get_fieldsets(request, obj) 
    if not obj: # this is an add form 
     if 'item_type' not in fieldsets[0][1]['fields']: 
      fieldsets[0][1]['fields'] += ('item_type',) 
    else: # this is a change form 
     fieldsets[0][1]['fields'] = tuple(x for x in fieldsets[0][1]['fields'] if x!='item_type') 
    return fieldsets 
21

Tôi có một số mã mẫu từ một dự án gần đây của tôi mà tôi tin rằng có thể giúp bạn. Trong ví dụ này, người dùng siêu có thể chỉnh sửa mọi trường, trong khi những người khác có trường "mô tả" bị loại trừ.

Lưu ý rằng tôi cho rằng bạn sẽ trả lại một lớp học Form từ get_form, đó có thể là lý do khiến bạn không hoạt động bình thường.

Dưới đây là ví dụ:

class EventForm(forms.ModelForm): 
    class Meta: 
     model = models.Event 
     exclude = ['description',] 

class EventAdminForm(forms.ModelForm): 
    class Meta: 
     model = models.Event 

class EventAdmin(admin.ModelAdmin): 

    def get_form(self, request, obj=None, **kwargs): 
     if request.user.is_superuser: 
      return EventAdminForm 
     else: 
      return EventForm 

admin.site.register(models.Event, EventAdmin) 
+0

Điều đó có vẻ thực sự hữu ích. Tôi đang ở giữa một thời hạn ngay bây giờ nhưng tôi sẽ cố gắng này ra vào tuần tới. PS Không cuộc gọi siêu kết quả của tôi trong một Biểu mẫu được trả về? Tôi chỉ sửa đổi các tham số và trả về những gì get_form sẽ tự quay trở lại. –

+0

Và những gì về việc sử dụng các fieldets với giải pháp này? Nếu chúng ta sử dụng get_forms, chúng ta dường như mất cấu hình cho các fields và cũng là widget javascript DateTimeField. Cảm ơn. – vmassuchetto

+1

https://docs.djangoproject.com/en/1.4/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_form dường như là giải pháp tốt hơn nhiều. @ ryan-duffield – Saurabh

6

Đây là giải pháp của tôi:

class MyModelAdmin(admin.ModelAdmin): 

    def get_form(self, request, obj=None, **kwargs): 
     if request.user.is_superuser: 
      self.exclude =() 
     else: 
      self.exclude = ('field_to_exclude',) 
     return super(MyModelAdmin, self).get_form(request, obj=None, **kwargs) 

Hy vọng có thể giúp

+1

Thay vì xóa trường, bạn có thể muốn làm cho nó chỉ đọc (Django 1.2 trở lên) - chỉ cần sử dụng self.readonly_fields thay vì self.exclude. – jturnbull

+0

Đây không phải là chủ đề an toàn. Hoặc nó chỉ an toàn chỉ vì bạn có điều kiện khác. Hãy thử sửa đổi kwargs ["exclude"] thay vì self.exclude. – pista329

3

Đừng thay đổi giá trị thuộc tính tự vì nó không an toàn. Bạn cần phải sử dụng bất kỳ móc để ghi đè lên các giá trị đó.

6

Để tạo biểu mẫu quản trị viên tùy chỉnh, chúng tôi đã xác định một lớp mới có thể được sử dụng làm mixin.Cách tiếp cận này khá linh hoạt:

  • ModelAdmin: định nghĩa một fieldset chứa tất cả các lĩnh vực

  • ModelForm: thu hẹp các lĩnh vực được hiển thị

  • FlexibleModelAdmin: trọng get_fieldsets-phương pháp ModelAdmin; trả về một fieldset giảm mà chỉ chứa các lĩnh vực quy định tại các hình thức quản trị


class FlexibleModelAdmin(object): 
    ''' 
    adds the possibility to use a fieldset as template for the generated form 
    this class should be used as mix-in 
    ''' 

    def _filterFieldset(self, proposed, form): 
     ''' 
     remove fields from a fieldset that do not 
     occur in form itself. 
     ''' 

     allnewfields = [] 
     fields = form.base_fields.keys() 
     fieldset = [] 
     for fsname, fdict in proposed: 
      newfields = [] 
      for field in fdict.get('fields'): 
       if field in fields: 
        newfields.append(field) 
       allnewfields.extend(newfields) 
      if newfields: 
       newentry = {'fields': newfields} 
       fieldset.append([fsname, newentry]) 

     # nice solution but sets are not ordered ;) 
     # don't forget fields that are in a form but were forgotten 
     # in fieldset template 
     lostfields = list(set(fields).difference(allnewfields)) 
     if len(lostfields): 
      fieldset.append(['lost in space', {'fields': lostfields}]) 

     return fieldset 

    def get_fieldsets(self, request, obj=None): 
     ''' 
     Hook for specifying fieldsets for the add form. 
     ''' 

     if hasattr(self, 'fieldsets_proposed'): 
      form = self.get_form(request, obj) 
      return self._filterFieldset(self.fieldsets_proposed, form) 
     else: 
      return super(FlexibleModelAdmin, self).get_fieldsets(request, obj) 

Trong mô hình quản trị bạn xác định fieldsets_proposed phục vụ như là mẫu và chứa tất cả các lĩnh vực.

class ReservationAdmin(FlexibleModelAdmin, admin.ModelAdmin): 

    list_display = ['id', 'displayFullName'] 
    list_display_links = ['id', 'displayFullName'] 
    date_hierarchy = 'reservation_start' 
    ordering = ['-reservation_start', 'vehicle'] 
    exclude = ['last_modified_by'] 

    # considered by FlexibleModelAdmin as template 
    fieldsets_proposed = (
     (_('General'), { 
      'fields': ('vehicle', 'reservation_start', 'reservation_end', 'purpose') # 'added_by' 
     }), 
     (_('Report'), { 
      'fields': ('mileage') 
     }), 
     (_('Status'), { 
      'fields': ('active', 'editable') 
     }), 
     (_('Notes'), { 
      'fields': ('note') 
     }), 
    ) 
    ....   

    def get_form(self, request, obj=None, **kwargs): 
     ''' 
     set the form depending on the role of the user for the particular group 
     ''' 

     if request.user.is_superuser: 
      self.form = ReservationAdminForm 
     else: 
      self.form = ReservationUserForm 

     return super(ReservationAdmin, self).get_form(request, obj, **kwargs) 

admin.site.register(Reservation, ReservationAdmin) 

Trong các mẫu biểu mẫu của bạn, bạn có thể xác định các trường cần loại trừ/đưa vào. get_fieldset() của lớp mixin đảm bảo rằng chỉ các trường được định nghĩa trong biểu mẫu đang được trả về.

class ReservationAdminForm(ModelForm): 
    class Meta: 
     model = Reservation 
     exclude = ('added_by', 'last_modified_by') 

class ReservationUserForm(BaseReservationForm): 
    class Meta: 
     model = Reservation 
     fields = ('vehicle', 'reservation_start', 'reservation_end', 'purpose', 'note') 
0

Bạn có thể làm fieldsetsform tính và họ đã phát ra tín hiệu để có được những hình thức mong muốn/fieldsets.

Các vấn đề liên quan