Это просто и работает с Django 1.4:
class ClientAdminForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(ClientAdminForm, self).__init__(*args, **kwargs)
# access object through self.instance...
self.fields['base_rate'].queryset = Rate.objects.filter(company=self.instance.company)
class ClientAdmin(admin.ModelAdmin):
form = ClientAdminForm
....
Вам не нужно указывать это в классе формы, но вы можете сделать это непосредственно в ModelAdmin, поскольку Django уже включает этот встроенный метод в ModelAdmin (из документации):
ModelAdmin.formfield_for_foreignkey(self, db_field, request, **kwargs)¶
'''The formfield_for_foreignkey method on a ModelAdmin allows you to
override the default formfield for a foreign keys field. For example,
to return a subset of objects for this foreign key field based on the
user:'''
class MyModelAdmin(admin.ModelAdmin):
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "car":
kwargs["queryset"] = Car.objects.filter(owner=request.user)
return super(MyModelAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
Еще более изящный способ сделать это (например, создать интерфейсный интерфейсный интерфейс, к которому могут обращаться пользователи) - создать подкласс ModelAdmin, а затем изменить методы, указанные ниже. В результате получается пользовательский интерфейс, который показывает ТОЛЬКО контент, связанный с ними, и позволяет вам (суперпользователю) видеть все.
Я переопределил четыре метода, первые два лишают пользователя возможности что-либо удалять, а также удаляют кнопки удаления с сайта администратора.
Третье переопределение фильтрует любой запрос, содержащий ссылку (в примере «пользователь» или «дикобраз» (просто в качестве иллюстрации).
Последнее переопределение фильтрует любое поле внешней клавиши в модели, чтобы отфильтровать доступные варианты, такие же, как базовый набор запросов.
Таким образом, вы можете представить простой в управлении фронтальный сайт администратора, который позволяет пользователям связываться с их собственными объектами, и вам не нужно вводить конкретные фильтры ModelAdmin, о которых мы говорили выше.
class FrontEndAdmin(models.ModelAdmin):
def __init__(self, model, admin_site):
self.model = model
self.opts = model._meta
self.admin_site = admin_site
super(FrontEndAdmin, self).__init__(model, admin_site)
удалить кнопки «удалить»:
def get_actions(self, request):
actions = super(FrontEndAdmin, self).get_actions(request)
if 'delete_selected' in actions:
del actions['delete_selected']
return actions
запрещает удаление разрешения
def has_delete_permission(self, request, obj=None):
return False
фильтрует объекты, которые можно просматривать на сайте администратора:
def get_queryset(self, request):
if request.user.is_superuser:
try:
qs = self.model.objects.all()
except AttributeError:
qs = self.model._default_manager.get_queryset()
return qs
else:
try:
qs = self.model.objects.all()
except AttributeError:
qs = self.model._default_manager.get_queryset()
if hasattr(self.model, ‘user’):
return qs.filter(user=request.user)
if hasattr(self.model, ‘porcupine’):
return qs.filter(porcupine=request.user.porcupine)
else:
return qs
Фильтрует выбор для всех полей Foreignkey на сайте администратора:
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if request.employee.is_superuser:
return super(FrontEndAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
else:
if hasattr(db_field.rel.to, 'user'):
kwargs["queryset"] = db_field.rel.to.objects.filter(user=request.user)
if hasattr(db_field.rel.to, 'porcupine'):
kwargs["queryset"] = db_field.rel.to.objects.filter(porcupine=request.user.porcupine)
return super(ModelAdminFront, self).formfield_for_foreignkey(db_field, request, **kwargs)