рдЬрд▓реНрджреА рдпрд╛ рдмрд╛рдж рдореЗрдВ, рдПрдХ Django рдбреЗрд╡рд▓рдкрд░ рдХреЛ рдПрдХ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝рддрд╛ рд╣реИ: рдЗрд╕реЗ рдХреИрд╕реЗ рдмрдирд╛рдпрд╛ рдЬрд╛рдП рддрд╛рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕рдВрд╢реЛрдзрд┐рдд рдпрд╛ рд╣рдЯрд╛ рди рд╕рдХреЗрдВ, рдпрд╛ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдПрдХ рд╣реА рдкреНрд░рдХрд╛рд░ рдХреА рд╡рд┐рднрд┐рдиреНрди рд╡рд╕реНрддреБрдУрдВ рдХреЛ рди рджреЗрдЦ рд╕рдХреЗрдВред
рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рдЖрдкрдХрд╛ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдЬрд╛рдирдХрд╛рд░реА рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╣реИред рд╡рд┐рднрд┐рдиреНрди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╡рд┐рднрд┐рдиреНрди рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рдкреНрд░рд╡реЗрд╢ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдХрд┐рд╕реА рдЕрдиреНрдп рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдирд╣реАрдВ рджреЗрдЦрдиреА рдЪрд╛рд╣рд┐рдПред рдПрдХ рдФрд░ рдПрдХ рд╣реА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХрдИ рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рдкреНрд░рд╡реЗрд╢ рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рд╡рд┐рднрд┐рдиреНрди рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╕реНрдерд┐рддрд┐ рд░рдЦрддрд╛ рд╣реИ - рдХрд╣реАрдВ рд╡рд╣ рдХреЗрд╡рд▓ рдЬрд╛рдирдХрд╛рд░реА рджреЗрдЦ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рдЕрдиреНрдп рдореЗрдВ - рдбреЗрдЯрд╛ рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВред рдХреБрдЫ рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХрд░реНрдорд┐рдпреЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рдкрдВрдЬреАрдХреГрдд рд╣реИ, рдФрд░ рджреВрд╕рд░реЗ рдореЗрдВ, рдХреЗрд╡рд▓ рдЙрд╕рдХреА рд╕реЗрд╡рд╛рдУрдВ рдХреЗ рдЙрдкрднреЛрдХреНрддрд╛ рдХреЗ рд░реВрдк рдореЗрдВред рдХреНрд░рдорд╢рдГ рдкрд╣реБрдВрдЪ рд╕реНрддрд░, рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд▓рдЧ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред
рдЗрди рдореБрджреНрджреЛрдВ рдореЗрдВ рдХрдИ рдкреИрдХреЗрдЬ рд╢рд╛рдорд┐рд▓ рд╣реИрдВ, рд╣рдо рдЙрдирдореЗрдВ рд╕реЗ рдПрдХ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗ - Django-Access ред рд╣рд░ рдХреЛрдИ рдЬреЛ рджрд┐рд▓рдЪрд╕реНрдкреА рд░рдЦрддрд╛ рд╣реИ рдЙрд╕реЗ рдмрд┐рд▓реНрд▓реА рдХреЗ рд▓рд┐рдП рдЖрдордВрддреНрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдЙрджрд╛рд╣рд░рдг
рдкреНрд░рд╕реНрддрд╛рд╡рдирд╛ рдореЗрдВ рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдЙрджрд╛рд╣рд░рдг рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред рд╣рдо рдорд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рджрд┐рд╢рд╛ рдХреА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╕рд░рд▓ рдбреЗрдЯрд╛ рдкреНрд░рдмрдВрдзрди рдкреНрд░рдгрд╛рд▓реА рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдкрд░рд┐рд╡рд╣рдиред рд╡рд┐рднрд┐рдиреНрди рдбреЗрдЯрд╛ рддрдХ рдкрд╣реБрдВрдЪ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ, рд╕рд┐рд╕реНрдЯрдо рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рдХрдИ рд╢реНрд░реЗрдгрд┐рдпреЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
- рдкреНрд░рд╢рд╛рд╕рдХ - рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд▓рд┐рдП рдХрд░реНрдорд┐рдпреЛрдВ рдХреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдкрд░ рдбреЗрдЯрд╛ рдореЗрдВ рд╣реЗрд░рдлреЗрд░ рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдЬреЛ рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╕реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рдкреНрд░рдмрдВрдзрд┐рдд, рдХрдиреЗрдХреНрдЯ рдФрд░ рдбрд┐рд╕реНрдХрдиреЗрдХреНрдЯ рдХрд░рддрд╛ рд╣реИ, рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдкрд╣реБрдВрдЪ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдмрджрд▓ рджреЗрддрд╛ рд╣реИ
 - рдХрд╛рд░реНрдорд┐рдХ - рд╕рдВрдкреВрд░реНрдг рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рдбреЗрдЯрд╛ рдХрд╛ рдкреНрд░рдмрдВрдзрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ: рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд▓рд┐рдП рдХрд░реНрдорд┐рдпреЛрдВ рдХреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдкрд░ рдбреЗрдЯрд╛ рдХреЛ рдЫреЛрдбрд╝рдХрд░, рд╕рднреА рдбреЗрдЯрд╛ рдмрдирд╛рдПрдБ, рд╣рдЯрд╛рдПрдВ, рдмрджрд▓реЗрдВ
 - рдСрдбрд┐рдЯрд░ - рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдбреЗрдЯрд╛ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЙрдиреНрд╣реЗрдВ рдмрджрд▓ рдирд╣реАрдВ рд╕рдХрддреЗ
 - рдЧреНрд░рд╛рд╣рдХ - рдХреЗрд╡рд▓ рдЙрд╕рдХреЗ рд╕рд╛рде рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдк рд╕реЗ рдмрд╛рддрдЪреАрдд рдХрд░рдиреЗ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд░рд┐рдХреЙрд░реНрдб рджреЗрдЦ рд╕рдХрддрд╛ рд╣реИ, рд╕рд╛рде рд╣реА рд╕рд╛рде рдЕрдкрдиреЗ рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╡реНрдпрдХреНрддрд┐рдЧрдд рдбреЗрдЯрд╛ рднреА рдмрджрд▓ рд╕рдХрддрд╛ рд╣реИ
 
рдХреИрд╕реЗ Django рдЕрдзрд┐рдХрд╛рд░ рдкреНрд░рдгрд╛рд▓реА рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП
, Django, django.contrib.auth. , Permission Group , , .
тАФ Django django-admin startproject sample.
Django, sample sample options .
- trans python manage.py startapp trans .
Project.
class Project(models.Model):
    name = models.CharField(
        max_length=256,
        db_index=True,
        verbose_name=_('Name'),
        help_text=_('Name of the project')
    )
    def __str__(self):
        return self.name
    class Meta:
        verbose_name = _('Project')
        verbose_name_plural = _('Projects')
. ProjectMember, .
class ProjectMember(models.Model):
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL, on_delete=models.CASCADE,
        verbose_name=_('User'), help_text=_('User who belongs to this project'),
        related_name='projects',
    )
    project = models.ForeignKey(
        Project, on_delete=models.CASCADE,
        verbose_name=_('Project'), help_text=_('Project to which this user belongs'),
        related_name='users',
    )
    allow_change = models.BooleanField(
        default=True,
        verbose_name=_('Allow Change'),
        help_text=_('Is the member allowed to change the project data?')
    )
    allow_manage = models.BooleanField(
        default=False,
        verbose_name=_('Allow Manage'),
        help_text=_('Is the member allowed to manage users for the project?')
    )
    def __str__(self):
        return _('%s -> %s') % (self.user, self.project)
    class Meta:
        verbose_name = _('Project Member')
        verbose_name_plural = _('Project Members')
        unique_together = (
            ('user', 'project'),
        )
, , . , , . , , - , .
тАФ , тАФ :
, , , -.
class Vehicle(models.Model):
    project = models.ForeignKey(
        Project, on_delete=models.CASCADE,
        verbose_name=_('Project'), help_text=_('Project to which this vehicle belongs'),
        related_name='vehicles',
    )
    code = models.CharField(
        max_length=256,
        db_index=True,
        verbose_name=_('Code'),
        help_text=_('Registration code')
    )
    def __str__(self):
        return self.code
    class Meta:
        verbose_name = _('Vehicle')
        verbose_name_plural = _('Vehicles')
        unique_together = (
            ('code', 'project'),
        )
class Driver(models.Model):
    project = models.ForeignKey(
        Project, on_delete=models.CASCADE,
        verbose_name=_('Project'), help_text=_('Project to which this driver belongs'),
        related_name='drivers',
    )
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL, on_delete=models.CASCADE,
        verbose_name=_('User'), help_text=_('User who is a driver'),
        related_name='driving',
    )
    def __str__(self):
        return _('%s [%s]') % (self.user, self.project)
    class Meta:
        verbose_name = _('Driver')
        verbose_name_plural = _('Drivers')
        unique_together = (
            ('user', 'project'),
        )
class Order(models.Model):
    project = models.ForeignKey(
        Project, on_delete=models.CASCADE,
        verbose_name=_('Project'), help_text=_('Project to which this order belongs'),
        related_name='orders',
    )
    client = models.ForeignKey(
        settings.AUTH_USER_MODEL, on_delete=models.CASCADE,
        verbose_name=_('Client'), help_text=_('Client getting an order'),
        related_name='orders',
    )
    vehicle = models.ForeignKey(
        Vehicle, on_delete=models.CASCADE,
        verbose_name=_('Vehicle'), help_text=_('Vehicle assigned to this order'),
        related_name='orders',
    )
    driver = models.ForeignKey(
        Driver, on_delete=models.CASCADE,
        verbose_name=_('Driver'), help_text=_('Driver assigned to this order'),
        related_name='orders',
    )
    start_time = models.DateTimeField(
        db_index=True,
        verbose_name=_("Start Time"),
        help_text=_("Time when the order is started")
    )
    stop_time = models.DateTimeField(
        db_index=True,
        verbose_name=_("Stop Time"),
        help_text=_("Time when the order is stopped")
    )
    def __str__(self):
        return _('%(start_time)s-%(stop_time)s %(client)s %(driver)s %(vehicle)s') % {
            'start_time': self.start_time,
            'stop_time': self.stop_time,
            'client': self.client,
            'driver': self.driver,
            'vehicle': self.vehicle,
        }
    class Meta:
        verbose_name = _('Order')
        verbose_name_plural = _('Orders')
access trans settings.py, python makemigrations trans python migrate.
, , admin.py trans. Django-Access.
?. -, Django-Access , , , Django, , , .
-, , , Django-Access, , Django, .
 @admin.register(Project)
class ProjectAdmin(AccessModelAdmin):
    fields = ['name']
    list_display = ['name']
    search_fields = ['name']
@admin.register(ProjectMember)
class ProjectMemberAdmin(AccessModelAdmin):
    fields = ['user', 'project', 'allow_manage', 'allow_change']
    list_display = ['user', 'project', 'allow_manage', 'allow_change']
    search_fields = ['user__username', 'user__first_name', 'user__last_name', 'project__name']
    list_filters = ['project', 'allow_manage', 'allow_change']
    autocomplete_fields = ['user', 'project']
    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "project":
            projects = AccessManager(Project).changeable(request)
            kwargs["queryset"] = projects
        return super(ProjectMemberAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
@admin.register(Vehicle)
class VehicleAdmin(AccessModelAdmin):
    fields = ['project', 'code']
    list_display = ['code', 'project']
    list_filters = ['project']
    search_fields = ['code']
    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "project":
            projects = Project.objects.filter(users__user=request.user, users__allow_change=True)
            kwargs["queryset"] = projects
        return super(VehicleAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
@admin.register(Driver)
class DriverAdmin(AccessModelAdmin):
    fields = ['project', 'user']
    list_display = ['user', 'project']
    list_filters = ['project']
    search_fields = ['user__username', 'user__first_name', 'user__last_name', 'project__name']
    autocomplete_fields = ['user', 'project']
    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "project":
            projects = Project.objects.filter(users__user=request.user, users__allow_change=True)
            kwargs["queryset"] = projects
        return super(DriverAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
@admin.register(Order)
class OrderAdmin(AccessModelAdmin):
    fields = ['project', 'client', 'vehicle', 'driver', 'start_time', 'stop_time']
    list_display = ['start_time', 'stop_time', 'client', 'driver', 'vehicle', 'project']
    list_filters = ['project', 'vehicle', 'driver']
    search_fields = ['client__username', 'client__first_name', 'client__last_name', 'project__name',]
    autocomplete_fields = ['client', 'vehicle', 'driver', 'project']
    date_hierarchy = 'start_time'
    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "project":
            projects = Project.objects.filter(users__user=request.user, users__allow_change=True)
            kwargs["queryset"] = projects
        return super(OrderAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
, .
, .
, , autocomplete:
admin.site.unregister(User)
admin.site.unregister(Group)
@admin.register(User)
class AccessUserAdmin(AccessControlMixin, UserAdmin):
    def get_readonly_fields(self, request, obj=None):
        readonly_fields = super(AccessUserAdmin, self).get_readonly_fields(request, obj) or []
        if request.user.is_superuser:
            return readonly_fields
        if not obj:
            return readonly_fields
        restrict = ['is_superuser', 'last_login', 'date_joined']
        if obj.pk != request.user.pk:
            restrict = ['is_superuser', 'last_login', 'date_joined', 'password', 'email']
        return [f for f in readonly_fields if f not in restrict] + restrict
    def get_list_display(self, request):
        fields = super(AccessUserAdmin, self).get_list_display(request) or []
        if request.user.is_superuser:
            return fields
        restrict = ['password', 'email']
        return [f for f in fields if not f in restrict]
    def _fieldsets_exclude(self, fieldsets, exclude):
        ret = []
        for nm, params in fieldsets:
            if 'fields' not in params:
                ret.append((nm, params))
                continue
            fields = []
            for f in params['fields']:
                if f not in exclude:
                    fields.append(f)
            pars = {}
            pars.update(params)
            pars['fields'] = fields
            ret.append((nm, pars))
        return ret
    def _fieldsets_only(self, fieldsets, only):
        ret = []
        for nm, params in fieldsets:
            if 'fields' not in params:
                ret.append((nm, params))
                continue
            fields = []
            for f in params['fields']:
                if f in only:
                    fields.append(f)
            pars = {}
            pars.update(params)
            pars['fields'] = fields
            ret.append((nm, pars))
        return ret
    def get_fieldsets(self, request, obj=None):
        fieldsets = list(super(AccessUserAdmin, self).get_fieldsets(request, obj)) or []
        fields = self.get_fields(request, obj=obj)
        return self._fieldsets_only(fieldsets, fields)
    def get_fields(self, request, obj=None):
        fields = list(super(AccessUserAdmin, self).get_fields(request, obj)) or []
        exclude = ['is_staff', 'groups', 'user_permissions']
        if not request.user.is_superuser:
            exclude = ['is_staff', 'is_superuser', 'groups', 'user_permissions']
            if obj and obj.pk != request.user.pk:
                exclude = ['is_staff', 'password', 'email', 'groups', 'user_permissions']
        return [f for f in fields if not f in exclude]
    def save_model(self, request, obj, form, change):
        obj.is_staff = True
        return super(AccessUserAdmin, self).save_model(request, obj, form, change)
, , , ( is_staff is_superuser), , , .
, authorize. , , .
?, . authorize INSTALLED_APPS settings.py, .
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'access',
    'trans',
    
    'authorize',
]
 python manage.py startapp authorize models.py. , .
?, models.py, , , , INSTALLED_APPS. , , .
 , , ( ) , . , , , .
, , , . , , , , . , , .
AccessManager.register_plugins({
    User: CompoundPlugin(
        CheckAblePlugin(
            appendable=(lambda model, request: 
                {} if request.user.id and request.user.projects.filter(allow_manage=True) else
                False
            ),
        ),
        ApplyAblePlugin(
            visible=(
                lambda queryset, request:
                    queryset if request.user.projects.filter(
                        allow_manage=True
                    ) else queryset.filter(
                        projects__project__users__user=request.user.id
                    ).distinct() or queryset.filter(
                        id=request.user.id
                    ).distinct()
            ),
            changeable=(lambda queryset, request: queryset.filter(id=request.user.id).distinct()),
            deleteable=(lambda queryset, request: queryset.filter(id=request.user.id).distinct())
        )
    ),
})
.
-, , , , , . , , , , .
-, , , . , , .
AccessManager.register_plugins({
    Project: CompoundPlugin(
        CheckAblePlugin(
            appendable=(lambda model, request: False),
        ),
        ApplyAblePlugin(
            visible=(lambda queryset, request: queryset.filter(
                users__user=request.user.id
            ).distinct()),
            changeable=(lambda queryset, request: queryset.filter(
                users__user=request.user.id,
                users__allow_manage=True
            ).distinct()),
            deleteable=(lambda queryset, request: queryset.none()),
        )
    ),
    ProjectMember: CompoundPlugin(
        CheckAblePlugin(
            appendable=(lambda model, request: {} if request.user.id and request.user.projects.filter(allow_manage=True) else False),
        ),
        ApplyAblePlugin(
            visible=(lambda queryset, request: queryset.filter(
                project__users__user=request.user.id
            ).distinct()),
            changeable=(lambda queryset, request: queryset.filter(
                project__users__user=request.user.id,
                project__users__allow_manage=True
            ).distinct()),
            deleteable=(lambda queryset, request: queryset.filter(
                project__users__user=request.user.id,
                project__users__allow_manage=True
            ).distinct()),
        )
    ),
})
, , . , , allow_change.
, тАФ , , () .
, , :
Driver тАФ ,Order тАФ , , , , .
.
AccessManager.register_plugins({
    Vehicle: CompoundPlugin(
        ApplyAblePlugin(
            visible=(lambda queryset, request: queryset.filter(
                project__users__user=request.user.id
            ).distinct()),
            changeable=(lambda queryset, request: queryset.filter(
                project__users__user=request.user.id,
                project__users__allow_change=True
            ).distinct()),
            deleteable=(lambda queryset, request: queryset.filter(
                project__users__user=request.user.id,
                project__users__allow_change=True
            ).distinct()),
        )
    ),
    Driver: CompoundPlugin(
        ApplyAblePlugin(
            visible=(lambda queryset, request: queryset.filter(
                Q(project__users__user=request.user.id) | Q(user=request.user)
            ).distinct()),
            changeable=(lambda queryset, request: queryset.filter(
                project__users__user=request.user.id,
                project__users__allow_change=True
            ).distinct()),
            deleteable=(lambda queryset, request: queryset.filter(
                project__users__user=request.user.id,
                project__users__allow_change=True
            ).distinct()),
        )
    ),
    Order: CompoundPlugin(
        ApplyAblePlugin(
            visible=(lambda queryset, request: queryset.filter(
                Q(
                    project__users__user=request.user.id
                ) | Q(
                    client=request.user
                ) | Q(
                    driver__user=request.user
                )
            ).distinct()),
            changeable=(lambda queryset, request: queryset.filter(
                project__users__user=request.user.id,
                project__users__allow_change=True
            ).distinct()),
            deleteable=(lambda queryset, request: queryset.filter(
                project__users__user=request.user.id,
                project__users__allow_change=True
            ).distinct()),
        )
    ),
})
?, .
, Django-Access , , .
- , . , . project, , .
ProjectMember:
    ...
    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "project":
            projects = AccessManager(Project).changeable(request)
            kwargs["queryset"] = projects
        return super(ProjectMemberAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
:
    ...
    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "project":
            projects = Project.objects.filter(users__user=request.user, users__allow_change=True)
            kwargs["queryset"] = projects
        return super(..., self).formfield_for_foreignkey(db_field, request, **kwargs)
( тАж ).
 . , Django, Django-Access , , Django. access.plugins.DjangoAccessPlugin, , .
settings.py. , , , , .
class SuperOnly(AccessPluginBase):
    def check_visible(self, model, request):
        return request.user.is_superuser and {}
    def check_changeable(self, model, request):
        return request.user.is_superuser and {}
    def check_appendable(self, model, request):
        return request.user.is_superuser and {}
    def check_deleteable(self, model, request):
        return request.user.is_superuser and {}
settings.py
ACCESS_DEFAULT_PLUGIN = "authorize.models.SuperOnly"
, , , .
Django-Access рдкреИрдХреЗрдЬ рдХреА рдорджрдж рд╕реЗ , рд╣рдордиреЗ рд▓рдЧрднрдЧ рд╕рднреА рдЖрд╡рд╢реНрдпрдХ рдирд┐рдпрдо рддреИрдпрд╛рд░ рдХрд┐рдП, рдФрд░ рд╡реНрдпрд╡рд╕реНрдерд╛рдкрдХ рдкреИрдирд▓ рдореЗрдВ рдЫреЛрдЯреЗ рдмрджрд▓рд╛рд╡реЛрдВ рджреНрд╡рд╛рд░рд╛ рдкрд╣реБрдВрдЪ рдкреНрд░рддрд┐рдмрдВрдз рдХреЗ рд╢реЗрд╖ рд╡рд┐рд╡рд░рдгреЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЧрдпрд╛ред
рд╣рдордиреЗ DBMS рдХреЛ рдкреНрд░рд╢реНрдиреЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рд╕рднреА рдПрдХреНрд╕реЗрд╕ рдкреНрд░рддрд┐рдмрдВрдз рдирд┐рдпрдо рддреИрдпрд╛рд░ рдХрд┐рдПред
рдЖрдк GitHub рднрдВрдбрд╛рд░ рдкрд░ рдЪрд▓ рд░рд╣реЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╛ рдкреВрд░реНрдг рд╕реНрд░реЛрдд рдХреЛрдб рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ