Проблема с настройкой Django-rules: has_perm всегда False для пользовательской модели пользователя

#python #django #debugging #django-rules

#python #django #отладка #django-rules

Вопрос:

Я новичок в Django. Я пытался настроить django-rules с пользовательской моделью пользователя, но продолжаю получать 404 при попытке доступа к странице. Вот как выглядит настройка:

Пользовательская модель пользователя

 class User(AbstractBaseUser, PermissionsMixin):

    class Meta:
        verbose_name = _('user')
        verbose_name_plural = _('users')

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True)

    first_name = models.CharField(max_length=200)
    last_name = models.CharField(max_length=200)

    email = models.EmailField(
        verbose_name='email address',
        max_length=255,
        unique=True,
    )

    is_active = models.BooleanField(default=False)

    objects = UserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    def __str__(self):
        return self.email
  

settings.py

 AUTHENTICATION_BACKENDS = (
    'rules.permissions.ObjectPermissionBackend',
    'django.contrib.auth.backends.ModelBackend',
)
  

установленные приложения

 INSTALLED_APPS = [
    # ...
    'rules.apps.AutodiscoverRulesConfig',
]
  

rules.py

 @rules.predicate
def is_organisation_member(user, organisation):
    """Check if user is an active organisation member"""
    m = get_if_exists(
        OrganisationMember,
        user=user,
        organisation=organisation,
        organisation__state=Organisation.LifecycleState.ACTIVE
    )
    if not m:
        return False
    if not m.is_active:
        return False
    return True

rules.add_perm('organisations.member',  (is_authenticated amp; is_active amp; is_organisation_member))
  

views.py

 def get_organisation_by_slug(request, *args, **kwargs):
    return get_object_or_404(Organisation, workspace_name=kwargs['workspace'])

@permission_required('organisations.member', fn=get_organisation_by_slug)
def OrganisationView(request, workspace):
    # ...
  

urls.py

 urlpatterns = [
    path('admin/', admin.site.urls),

    # ...

    # organisation
    path('<str:workspace>', v.OrganisationView, name="organisation-show"),
    # ...
]
  

Согласно отладке, is_organisation_member возвращает True, но пользователь по-прежнему получает ошибку 404 при попытке просмотреть страницу (без декоратора django-rules permission_required страница работает). Есть идеи, почему я получаю ответ 404?

Комментарии:

1. Не могли бы вы показать нам полную ошибку, поскольку вы обычно получаете эту ошибку, если ваш urls.py это неправильно или если вы ПОЛУЧАЕТЕ вместо POST или что-то в этом роде?

2. Конечно: Page not found (404) Request Method: GET Request URL: http://127.0.0.1:8000/abc1 Raised by: bb.views.OrganisationView Not found You're seeing this error because you have DEBUG = True in your Django settings file. Change that to False, and Django will display a standard 404 page. URL: 127.0.0.1:8000/abc1 . abc1 — это имя организации, и оно находится в базе данных. URL работает, когда я удаляю декоратор.

3. не могли бы вы добавить свой urls.py

4. Конечно, готово. Спасибо!

5. @AyanSh спасибо за рассмотрение вопроса, когда вы спросили о urls.py Я начал задаваться вопросом, была ли проблема на самом деле в другом месте, и начал настраивать код в разных местах.

Ответ №1:

без permission_required декоратора django-rules страница работает

Это было правдой только наполовину! Это сработало, когда генератор был удален и присутствовали существующие тестовые данные. Но когда запрос ничего не вернул, появилась ошибка 404.

Я неправильно предположил, что проблема заключалась в настройке правил, но после удаления декоратора ошибка все еще сохранялась. Раньше я не видел эту ошибку, потому что у меня всегда были автоматически сгенерированные тестовые данные (список проектов), но не в этот раз. Итак, после просмотра функции просмотра я понял, что вызывал ошибку 404, когда запрос проекта возвращал пустой список:

 @permission_required('organisations.member', fn=get_organisation_by_slug)
def OrganisationView(request, workspace):

    # Query strings:
    # Extract 'tab' value appended to url as
    # ?tab=projects
    tab = request.GET.get('tab', '')
    
    # Get organisation
    try:
        o = Organisation.objects.get(workspace_name=workspace)
    except Organisation.DoesNotExist:
        raise Http404("Not found.")

    if tab == 'projects':
        # Get project list 
        try:
            p = Project.objects.filter(organisation__workspace_name=workspace) 
                .order_by('-created_at')
        except Project.DoesNotExist:
            raise Http404("Not found")
    else:
        raise Http404("Not found...") # ERROR CAUSED BY THIS LINE
        # To fix the error, I have removed the above line and added the below query
        # p = Project.objects.filter(organisation__workspace_name=workspace) 
        #     .order_by('-created_at')

    # Set context 
    context = {
        'o': o,
        'projects': p
    }

    return render(request, 'bb/home.html', context)
  

Поскольку я был уверен, что с моим представлением все в порядке, я не опубликовал полную функцию, из-за чего кому-либо еще было трудно исправить ошибку. Я понял, что ошибка была в представлении после добавления has_perm(self, perm, obj=None): return True в пользовательскую модель, но все еще получаю ошибку 404.