Trong Django, làm cách nào để kiểm tra xem người dùng có thuộc một nhóm nhất định không?


146

Tôi đã tạo một nhóm tùy chỉnh trong trang quản trị của Django.

Trong mã của tôi, tôi muốn kiểm tra xem người dùng có thuộc nhóm này không. Làm thế nào để làm điều đó?

Câu trả lời:


117

Bạn có thể truy cập các nhóm chỉ đơn giản thông qua các groupsthuộc tính trên User.

from django.contrib.auth.models import User, Group

group = Group(name = "Editor")
group.save()                    # save this new group for this example
user = User.objects.get(pk = 1) # assuming, there is one initial user 
user.groups.add(group)          # user is now in the "Editor" group

rồi user.groups.all()trở về [<Group: Editor>].

Ngoài ra, và trực tiếp hơn, bạn có thể kiểm tra xem người dùng aa có ở trong một nhóm hay không bằng cách:

if django_user.groups.filter(name = groupname).exists():

    ...

Lưu ý rằng đó cũnggroupname có thể là đối tượng Django Group thực tế.


112
Việc kiểm tra thực tế sẽ làif user.groups.filter(name=group_name).count(): # do something
Maccesch

144
hoặc sử dụng .exists () thay vì .count ()
Lie Ryan

3
Câu hỏi là về truy vấn mô hình Người dùng cho các nhóm mà nó thuộc về, không phải làm thế nào để khởi tạo ... -.-
Jcc.Sanabria

210

Đối tượng Người dùng của bạn được liên kết với đối tượng Nhóm thông qua mối quan hệ ManyToMany .

Do đó, bạn có thể áp dụng phương pháp lọc cho user.groups .

Vì vậy, để kiểm tra xem một Người dùng cụ thể có thuộc một nhóm nhất định không (ví dụ "Thành viên"), chỉ cần thực hiện việc này:

def is_member(user):
    return user.groups.filter(name='Member').exists()

Nếu bạn muốn kiểm tra xem một người dùng nhất định có thuộc nhiều nhóm nhất định hay không, hãy sử dụng toán tử __in như vậy:

def is_in_multiple_groups(user):
    return user.groups.filter(name__in=['group1', 'group2']).exists()

Lưu ý rằng các chức năng đó có thể được sử dụng với trình trang trí @user_passes_test để quản lý quyền truy cập vào chế độ xem của bạn:

from django.contrib.auth.decorators import login_required, user_passes_test
@login_required
@user_passes_test(is_member) # or @user_passes_test(is_in_multiple_groups)
def myview(request):
    # Do your processing

Hy vọng điều này giúp đỡ


4
Tôi không chắc chắn về hoạt động bên trong của việc truy cập DB của django, nhưng điều này có vẻ hiệu quả hơn rất nhiều so với một số gợi ý khác, như đưa tất cả người dùng vào một nhóm và thực hiện một con trăn tiêu chuẩn user in groups(hoặc ngược lại).
brianmearn

1
Bạn không phải thêm .exists()vào cuối để trả về một boolean? Nếu không is_member()is_in_multiple_groups()sẽ trả về một QuerySet, có thể không cho kết quả mong muốn.
Michael Bates

4
Theo tài liệu của Django, nó thực sự nhanh hơn là để sử dụng tồn tại () vì nó không đánh giá queryset: docs.djangoproject.com/en/dev/ref/models/querysets/#exists
Charlesthk

5
Bạn có thể muốn có siêu người dùng vượt qua bài kiểm tra (mà không cần truy vấn cơ sở dữ liệu):def is_member(user): return user.is_superuser or user.groups.filter(...
Dave

is_in_multiple_groupscó thể được đặt tên rõ ràng hơn is_in_some_groupsvì nó không yêu cầu người dùng đó phải là thành viên của tất cả các nhóm
PeterVermont

15

Nếu bạn cần danh sách người dùng trong một nhóm, bạn có thể thực hiện việc này thay thế:

from django.contrib.auth.models import Group
users_in_group = Group.objects.get(name="group name").user_set.all()

và sau đó kiểm tra

 if user in users_in_group:
     # do something

để kiểm tra xem người dùng có ở trong nhóm không


5
Điều này không mở rộng tốt cho các trang web có nhiều hơn một số ít người dùng, vì nó sẽ tải bảng người dùng tập hợp con lớn vào bộ nhớ mỗi khi nó chạy.
bhuber

1
user.groups.filter(name="group name").exists()nên làm việc tốt Giải pháp bạn đã viết sử dụng hai truy vấn và do đó không tối ưu lắm.
Noopur Phalak

như nó nói, "nếu bạn cần danh sách người dùng trong một nhóm" ...
Mark Chackerian

15

Nếu bạn không cần ví dụ người dùng trên trang web (như tôi đã làm), bạn có thể làm điều đó với

User.objects.filter(pk=userId, groups__name='Editor').exists()

Điều này sẽ chỉ tạo ra một yêu cầu cho cơ sở dữ liệu và trả về một boolean.


11

Nếu người dùng thuộc một nhóm nhất định hay không, có thể được kiểm tra trong các mẫu django bằng cách sử dụng:

{% if group in request.user.groups.all %} "some action" {% endif %}


1
điều này không hiệu quả với tôi, dường như yêu cầu so sánh nhóm với tên nhóm
vòi vào

10

Bạn chỉ cần một dòng:

from django.contrib.auth.decorators import user_passes_test  

@user_passes_test(lambda u: u.groups.filter(name='companyGroup').exists())
def you_view():
    return HttpResponse("Since you're logged in, you can see this text!")

4
Mặc dù không phải mã rất sạch và không thể tái sử dụng, nhưng +1 để nhận mã thành một dòng.
WhyNotHugo

1

Chỉ trong trường hợp nếu bạn muốn kiểm tra nhóm người dùng thuộc danh sách nhóm được xác định trước:

def is_allowed(user):
    allowed_group = set(['admin', 'lead', 'manager'])
    usr = User.objects.get(username=user)
    groups = [ x.name for x in usr.groups.all()]
    if allowed_group.intersection(set(groups)):
       return True
    return False


1

Tôi có tình huống tương tự, tôi muốn kiểm tra xem người dùng có thuộc một nhóm nhất định không. Vì vậy, tôi đã tạo tập tin mới utils.py nơi tôi đặt tất cả các tiện ích nhỏ giúp tôi trong toàn bộ ứng dụng. Ở đó, tôi có định nghĩa này:

utils.py

def is_company_admin(user):
    return user.groups.filter(name='company_admin').exists()

vì vậy về cơ bản tôi đang kiểm tra xem người dùng có thuộc nhóm company_admin hay không và rõ ràng tôi đã gọi hàm này là_company_admin .

Khi tôi muốn kiểm tra xem người dùng có ở company_admin không, tôi chỉ cần làm điều này:

views.py

from .utils import *

if is_company_admin(request.user):
        data = Company.objects.all().filter(id=request.user.company.id)

Bây giờ, nếu bạn muốn kiểm tra tương tự trong mẫu của mình, bạn có thể thêm is_user_admin trong ngữ cảnh của mình, đại loại như thế này:

views.py

return render(request, 'admin/users.html', {'data': data, 'is_company_admin': is_company_admin(request.user)})

Bây giờ bạn có thể đánh giá phản hồi của bạn trong một mẫu:

users.html

{% if is_company_admin %}
     ... do something ...
{% endif %}

Giải pháp đơn giản và sạch sẽ, dựa trên các câu trả lời có thể tìm thấy trước đó trong chủ đề này, nhưng được thực hiện khác nhau. Hy vọng nó sẽ giúp được ai đó.

Đã thử nghiệm trong Django 3.0.4.


Trong bạn data = Company.objects.all().filter(id=request.user.company.id), Công ty biểu thị điều gì? Đó có phải là mô hình của bạn?
Hayden

Có @hayden, trong trường hợp này Công ty là mô hình của tôi.
Branko Radojevic

0

Trong một dòng:

'Groupname' in user.groups.values_list('name', flat=True)

Điều này đánh giá một trong hai Truehoặc False.


3
Điều này là không hiệu quả, vì nó sẽ lấy nhiều dữ liệu hơn, và sau đó hoạt động trên phía django. Nó tốt hơn để sử dụng .exists()để cho db làm việc.
WhyNotHugo

0

Tôi đã làm nó theo cách sau. Có vẻ không hiệu quả nhưng tôi không có cách nào khác trong tâm trí:

@login_required
def list_track(request):

usergroup = request.user.groups.values_list('name', flat=True).first()
if usergroup in 'appAdmin':
    tracks = QuestionTrack.objects.order_by('pk')
    return render(request, 'cmit/appadmin/list_track.html', {'tracks': tracks})

else:
    return HttpResponseRedirect('/cmit/loggedin')

0

User.objects.filter(username='tom', groups__name='admin').exists()

Truy vấn đó sẽ thông báo cho bạn người dùng: "tom" có thuộc nhóm "quản trị viên" hay không


nhóm__name với dấu gạch dưới kép
Trung Lê

0

Tôi đã làm nó như thế này. Đối với nhóm có tên Editor.

# views.py
def index(request):
    current_user_groups = request.user.groups.values_list("name", flat=True)
    context = {
        "is_editor": "Editor" in current_user_groups,
    }
    return render(request, "index.html", context)

bản mẫu

# index.html
{% if is_editor %}
  <h1>Editor tools</h1>
{% endif %}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.