ใน Django ฉันจะตรวจสอบว่าผู้ใช้อยู่ในกลุ่มใดกลุ่มหนึ่งได้อย่างไร


147

ฉันสร้างกลุ่มที่กำหนดเองในไซต์ผู้ดูแลระบบของ Django

ในรหัสของฉันฉันต้องการตรวจสอบว่าผู้ใช้อยู่ในกลุ่มนี้หรือไม่ ฉันจะทำอย่างไร

คำตอบ:


118

คุณสามารถเข้าถึงกลุ่มก็ผ่านแอตทริบิวต์บนgroupsUser

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

แล้วผลตอบแทนuser.groups.all()[<Group: Editor>]

หรืออีกทางหนึ่งโดยตรงคุณสามารถตรวจสอบว่าผู้ใช้อยู่ในกลุ่มโดย:

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

    ...

โปรดทราบว่าgroupnameสามารถนอกจากนี้ยังเป็นจริงวัตถุ Django กลุ่ม


112
การตรวจสอบที่แท้จริงจะเป็นif user.groups.filter(name=group_name).count(): # do something
Maccesch

144
หรือใช้. exists () แทน. นับ ()
Lie Ryan

3
คำถามนี้เกี่ยวกับการค้นหาโมเดลผู้ใช้สำหรับกลุ่มที่เป็นสมาชิกไม่ใช่วิธีสร้างอินสแตนซ์ของฉัน ... -.-
Jcc.Sanabria

210

วัตถุผู้ใช้ของคุณเชื่อมโยงกับวัตถุกลุ่มผ่านความสัมพันธ์ManyToMany

คุณจึงสามารถใช้กรองวิธีการในการuser.groups

ดังนั้นเพื่อตรวจสอบว่าผู้ใช้ที่ได้รับอยู่ในกลุ่มใดกลุ่มหนึ่ง ("สมาชิก" สำหรับตัวอย่าง) เพียงแค่ทำสิ่งนี้:

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

หากคุณต้องการตรวจสอบว่าผู้ใช้ที่ได้รับอยู่ในกลุ่มมากกว่าหนึ่งกลุ่มให้ใช้ตัวดำเนินการ__inดังนี้:

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

โปรดทราบว่าฟังก์ชั่นเหล่านี้สามารถใช้กับ@user_passes_test decorator เพื่อจัดการการเข้าถึงมุมมองของคุณ:

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

หวังว่าความช่วยเหลือนี้


4
ฉันไม่แน่ใจเกี่ยวกับการทำงานภายในของการเข้าถึงฐานข้อมูลของ django แต่ดูเหมือนว่าจะมีประสิทธิภาพมากขึ้นจากนั้นก็มีคำแนะนำอื่น ๆ เช่นรับผู้ใช้ทั้งหมดในกลุ่มและทำ python มาตรฐานuser in groups(หรือกลับกัน)
brianmearns

1
คุณไม่ต้องเพิ่ม.exists()ท้ายเพื่อส่งคืนบูลีนหรือไม่? มิฉะนั้นis_member()และis_in_multiple_groups()จะส่งคืนQuerySetซึ่งอาจไม่ให้ผลลัพธ์ที่ต้องการ
Michael Bates

4
ตามเอกสารของ Django จะใช้งานได้เร็วขึ้นแน่นอน () เนื่องจากไม่ได้ประเมินชุดข้อมูล: docs.djangoproject.com/en/dev/ref/models/querysets/#exists
Charlesthk

5
คุณอาจต้องการให้ superuser ผ่านการทดสอบ (โดยไม่ต้องสืบค้นฐานข้อมูล):def is_member(user): return user.is_superuser or user.groups.filter(...
เดฟ

is_in_multiple_groupsสามารถตั้งชื่ออย่างชัดเจนมากขึ้นis_in_some_groupsเพราะไม่ต้องการให้ผู้ใช้ที่เป็นสมาชิกของทุกกลุ่ม
PeterVermont

15

หากคุณต้องการรายชื่อผู้ใช้ที่อยู่ในกลุ่มคุณสามารถทำได้ดังนี้:

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

จากนั้นตรวจสอบ

 if user in users_in_group:
     # do something

เพื่อตรวจสอบว่าผู้ใช้อยู่ในกลุ่มหรือไม่


5
วิธีนี้ใช้ไม่ได้กับไซต์ที่มีผู้ใช้มากกว่าจำนวนเล็กน้อยเนื่องจากจะโหลดตารางผู้ใช้ชุดย่อยขนาดใหญ่ลงในหน่วยความจำทุกครั้งที่เรียกใช้
bhuber

1
user.groups.filter(name="group name").exists()ควรทำงานได้ดี โซลูชันที่คุณเขียนใช้สองแบบสอบถามและดังนั้นจึงไม่ดีที่สุด
Noopur Phalak

ตามที่กล่าวไว้ว่า "ถ้าคุณต้องการรายชื่อผู้ใช้ที่อยู่ในกลุ่ม" ...
Mark Chackerian

15

หากคุณไม่ต้องการอินสแตนซ์ผู้ใช้บนไซต์ (อย่างที่ฉันทำ) คุณสามารถทำได้

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

สิ่งนี้จะสร้างคำขอเดียวไปยังฐานข้อมูลและส่งคืนบูลีน


11

หากผู้ใช้อยู่ในกลุ่มใดกลุ่มหนึ่งหรือไม่สามารถตรวจสอบในเทมเพลต django โดยใช้:

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


1
สิ่งนี้ใช้ไม่ได้สำหรับฉันดูเหมือนว่าต้องมีการเปรียบเทียบกลุ่มกับชื่อกลุ่ม
hosein

10

คุณต้องการเพียงหนึ่งบรรทัด:

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
แม้ว่าโค้ดที่ไม่สะอาดมากและไม่สามารถนำกลับมาใช้ใหม่ได้ แต่ +1 สำหรับการทำให้เป็นหนึ่งบรรทัด
ทำไม NotHugo

1

ในกรณีที่คุณต้องการตรวจสอบกลุ่มผู้ใช้ที่อยู่ในรายการกลุ่มที่กำหนดไว้ล่วงหน้า:

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

ฉันมีสถานการณ์ที่คล้ายกันฉันต้องการทดสอบว่าผู้ใช้อยู่ในกลุ่มใดกลุ่มหนึ่งหรือไม่ ดังนั้นฉันจึงสร้างไฟล์ใหม่ utils.py ที่ซึ่งฉันวางยูทิลิตี้เล็ก ๆ ทั้งหมดที่ช่วยฉันในการใช้งานทั้งหมด ที่นั่นฉันมีคำจำกัดความนี้:

utils.py

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

ดังนั้นโดยทั่วไปฉันกำลังทดสอบว่าผู้ใช้อยู่ในกลุ่มcompany_admin หรือไม่และเพื่อความชัดเจนฉันได้เรียกใช้ฟังก์ชันนี้ว่าis_company_admin is_company_admin

เมื่อฉันต้องการตรวจสอบว่าผู้ใช้อยู่ในcompany_adminฉันแค่ทำสิ่งนี้:

views.py

from .utils import *

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

ตอนนี้หากคุณต้องการทดสอบแบบเดียวกันในเทมเพลตคุณสามารถเพิ่มis_user_adminในบริบทของคุณได้ดังนี้:

views.py

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

ตอนนี้คุณสามารถประเมินการตอบสนองของคุณในเทมเพลต:

users.html

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

วิธีแก้ปัญหาที่ง่ายและสะอาดโดยอ้างอิงจากคำตอบที่พบได้ในหัวข้อนี้ แต่แตกต่างกันไป หวังว่ามันจะช่วยใครซักคน

ทดสอบใน Django 3.0.4


ใน บริษัท ของคุณdata = Company.objects.all().filter(id=request.user.company.id)หมายถึงอะไร นั่นคือรูปแบบของคุณหรือไม่
เฮย์เดน

ใช่ @ เฮย์เดนในกรณีนี้ บริษัท คือโมเดลของฉัน
Branko Radojevic

0

ในหนึ่งบรรทัด:

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

ประเมินนี้อย่างใดอย่างหนึ่งหรือTrueFalse


3
นี่เป็นสิ่งที่ไม่มีประสิทธิภาพเนื่องจากมันจะดึงข้อมูลได้มากขึ้นจากนั้นจึงใช้งานมันที่ด้าน django มันจะดีกว่าที่จะใช้.exists()เพื่อให้ db ทำงาน
WhyNotHugo

0

ฉันทำตามวิธีต่อไปนี้แล้ว ดูเหมือนไม่มีประสิทธิภาพ แต่ฉันไม่มีวิธีอื่นในใจ:

@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()

ข้อความค้นหานั้นจะแจ้งให้ผู้ใช้ทราบ: "ทอม" ไม่ว่าจะอยู่ในกลุ่ม "ผู้ดูแลระบบ" หรือไม่ก็ตาม


groups__name ที่มีเครื่องหมายขีดล่างคู่
Trung Lê

0

ฉันทำอย่างนี้ 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)

แบบ

# index.html
{% if is_editor %}
  <h1>Editor tools</h1>
{% endif %}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.