首页 > 解决方案 > 如何在 django 应用程序中授予多个登录对一个基于关键字的数据集的访问权限

问题描述

这是我正在处理的场景:我有创建记录的 django 应用程序,我称之为会话:

博客模型.py

class Session(models.Model):
    uid = models.CharField(max_length=50, blank=True)
    cid = models.CharField(max_length=50, blank=True)
    action_type = models.CharField(max_length=50, blank=True)
    action_name = models.CharField(max_length=50, blank=True)
    action_value = models.CharField(max_length=50, blank=True)
    session_date = models.DateTimeField(auto_now_add=True)
    client = models.CharField(max_length=50, blank=True)

我有一个显示图表的仪表板页面和一个将记录显示为表格的数据库页面:

博客网址.py

path('', auth_views.LoginView.as_view(template_name='users/login.html'), name='blog-home'),
path('<str:username>/dashboard/', views.dashboard and DashboardListView.as_view(), name='blog-dashboard'),
path('<str:username>/database/', views.database and SessionListView.as_view(), name='blog-database'),

因此,当您登录时,我SessionListView.as_view()会遍历整个数据库并仅显示 Session.client == url 的“用户名”值的那些记录。

示例:当用户:DummyCo 登录 ( www.website.com/DummyCo/database/ ) 时,他们只会看到 Session.client 字段为“DummyCo”的会话记录。到目前为止效果很好。

但问题是:我现在需要为用户提供多个登录名才能看到相同的仪表板和数据库页面。

示例:jim@DummyCo.com 和 amy@DummyCo.com 都需要查看 DummyCo 记录,但如果我为他们提供自己的登录名,那么他们在 url 中的用户名将不匹配,因此 DummyCo 记录不会显示。我认为使用内置的 django Groups 将是一个解决方案,但这似乎只有助于后端的身份验证和权限。我还使用 Profile 模型扩展了我的用户模型:

用户/模型.py

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    group = models.ForeignKey(Group, blank=True, null=True, default=None, on_delete=models.SET_DEFAULT)
    image = models.ImageField(default='default.jpg', upload_to='profile_pics')
    user_client = models.CharField(max_length=50, blank=True, null=True, default=None)

    def __str__(self):
        return f'{self.user.username} Profile'

我创建了user_client模型字段以尝试将配置文件(以及用户)与 Session.client 字段连接起来:而不是<str:username>/database/我认为我可以<str:client_user>/database/在 Jim 和 Amy 的个人资料上使用并简单地用“DummyCo”填充该字段来让他们访问记录。

我在几个地方读到,处理这个问题的关键是尽早或在我构建应用程序之前将用户模型从一对一切换到多对一类型。不幸的是,我已经在这个项目中投入了大量的工作。我还读到我应该将内置的用户模型视为更多的帐户而不是用户。那么有没有一种简单的方法可以让多个用户访问一个用户/帐户?

另外,以下是观点:

博客/views.py

class SessionListView(LoginRequiredMixin, ListView):
    model = Session, Profile
    template_name = 'blog/database.html'
    context_object_name = 'sessions'
    ordering = ['-session_date']
    paginate_by = 25

    def get_queryset(self):
        user = get_object_or_404(User, username=self.kwargs.get('username'))
        return Session.objects.filter(client=user).order_by('-session_date')

    def get_context_data(self, **kwargs):
        user = get_object_or_404(User, username=self.kwargs.get('username'))
        context = super().get_context_data(**kwargs)
        context['distinct_campaigns'] = Session.objects.filter(client=user).values('cid').distinct().order_by('cid')
        context['distinct_action_types'] = Session.objects.filter(client=user)\
        .values('action_type')\
        .distinct().order_by('action_type')
        return context

@ login_required()
def database(request):
    context = {
    'sessions': Session.objects.all()
    }
    return render(request, 'blog/database.html', context, {'title': 'Database'})

标签: pythondjangodjango-models

解决方案


好的,我想出了一个解决方案:

我以为我需要在 for 循环中显示我的查询集的 html 文件上做一些技巧,sessions但事实证明可以在我的 views.py 文件中进行调整。在此更新之前,我的 views.py 看起来像这样:

class SessionListView(LoginRequiredMixin, ListView):
    model = Session, Profile
    template_name = 'blog/database.html'
    context_object_name = 'sessions'
    ordering = ['-session_date']
    paginate_by = 25

    def get_queryset(self):
        user = get_object_or_404(User, username=self.kwargs.get('username'))
        return Session.objects.filter(client=user).order_by('-session_date')

    def get_context_data(self, **kwargs):
        user = get_object_or_404(User, username=self.kwargs.get('username'))
        context = super().get_context_data(**kwargs)
        context['distinct_campaigns'] = Session.objects.filter(client=user).values('cid').distinct().order_by('cid')
        context['distinct_action_types'] = Session.objects.filter(client=user)\
            .values('action_type')\
            .distinct().order_by('action_type')
        return context

我意识到def get_queryset(self)正在获取登录用户名,然后查看完整数据库并添加与登录用户(即 DummyCo)的值具有相同 session.client 值的所有记录。所以为了让这个像'DummyCo_Sally'这样的用户工作,我改变了def中的逻辑,如下所示:

class SessionListView(LoginRequiredMixin, ListView):
    # gets the actual user (i.e. DummyCo_Sally)
    user = get_object_or_404(User, username=self.kwargs.get('username'))
    # turns user to a string
    user_string = str(user)
    # designates the _ as the separator 
    sep = '_'
    # strips off _ and everything after it
    stripped_user = user_string.split(sep, 1)[0]
    # establishes the queryset as 'DummyCo' even though 'DummyCo_sally' is logged in
    return Session.objects.filter(client=stripped_user).order_by('-session_date')

我怀疑这种方法是处理多个用户查看一个伞形数据集的最佳方法,但它对我有用。此方法还可能为具有面向公众的用户注册的应用程序带来安全风险。但这对我有用。


推荐阅读