Схема на потребителските роли в Django

Страхотна поздравителна общност

Въпросът ми е свързан с вида управление на потребителите и потребителите на схемата в Django. В началото ви моля да се извините само в случай, че въпросите ми могат да бъдат твърде „новобранци“ или безсмислени, започвам да се свързвам с Django Потребителски схеми и различните им възможности за работа в проектите.

Имам следната ситуация.

Създавам приложение, в което ще имам три различни типа потребители:

  • медицински
  • Търпелив
  • Физиотерапевт

Използвам схемата за удостоверяване на Django по подразбиране (django.contrib.auth).

Първоначално мислех в тази схема на обекти, в които таблицата User е таблицата auth_user, в която Django запазва създадените потребители:

„Схемата

Имам полетата is_patient, is_medical и is_physiotherapist като булеви атрибути в таблицата User.

Като конкретен детайл разбирам, че в модела по подразбиране на Django потребителят не е възможно да променя или добавя атрибути или полета.

Това е важна и мощна причина да не мога да добавя булевите полета is_patient, is_medical и is_physiotherapist в таблицата с потребители.

Класическа препоръка е да разширите потребителския модел с таблица с потребителски профили, в която добавям полета или атрибути към потребителския модел чрез връзка OneToOne. Основна проба е следната:

„Разширяване

По този начин разбирам, че моите потребители в Django могат да имат полевата снимка и да я качат в даден момент ...

Възползвайки се от предишното, следната схема може да бъде подходяща или може да бъде алтернатива за управление на потребителски роли (patient, medical и physiotherapist потребителски типове)?

„Помислена

Ще имам връзки между:

  • Потребителски медицински и потребителски пациенти

  • потребителски физиотерапевт и потребителски пациенти

и така между тях и другите маси...

При този подход тези взаимоотношения няма ли да бъдат засегнати?

Различните потребители ще бъдат запазени между таблицата Users и UserProfile. Това добра практика ли е в смисъл на мащабируемост? Моите таблици може да се сринат или моята база данни?


Освен това съм виждал и други алтернативи като:

  1. Ролева таблица/модел

Ще имам независима или отделна ролева таблица/модел и че това може да бъде свързано с потребителския модел на Django (един потребител може да има много роли по пример) Този подход може да бъде полезен, когато искам да съхранявам ексклузивна информация за роля в specia ?

  1. Разрешения и оторизация на Django

Пренебрегвам или не знам степента на детайлност, която ми позволява да работя. По един единствен начин видях, че системата за разрешения и оторизации ми позволява да работя с операции за създаване, редактиране и премахване....

Тук мога ли да видя създаването на групи? Например медицинска група и да им разпределите разрешения и да свържете тези разрешения с потребителите, които съставят групата? Това друга добра алтернатива ли е? Тази опция изглежда по-единична, въпреки че не знам дали потребителят може да извърши някои операции според груповите привилегии, които имат ... Не знам дали това мислене е правилно/правилно

  1. AUTH_USER_MODEL Създаване на персонализиран потребителски модел

Изискванията ми за пациенти, медицински и физиотерапевтични потребители изискват изграждане на персонализиран потребителски модел?


person bgarcial    schedule 10.12.2015    source източник
comment
здравей, има ли нещо липсващо или незадоволително в отговора ми? :) би било чудесно да получите обратна връзка!   -  person Ire    schedule 18.12.2015
comment
@Ire, отговорът ти беше много полезен за мен. С някаква друга ориентация избрах да персонализирам моя Потребителски модел и да го свържа с моделите Medic, Patient, Physio във връзка OneToOne Вижте тези фигури cldup.com/lqB3367kAp.png - cldup.com/jxVsgfneGb.png) и когато добавям атрибутите в Потребител, трябваше да персонализирам своите администраторски формуляри, за да се показват там.   -  person bgarcial    schedule 18.12.2015
comment
@Ire, малко не разбирам, когато казвате: Наличието на персонализирани модели и групи би било излишно и би направило приложението ви по-трудно за поддръжка. Всъщност все още не съм пробвал с процеса на упълномощаване, но съм съгласен с вас да създавате групи и да изисквате дали конкретен потребител (пациент, лекар или физиотерапевт) съществува и принадлежи към група ...   -  person bgarcial    schedule 18.12.2015
comment
Защо е по-добре да го направите изрично, както е показано по-долу (по този начин е по-малко вероятно да получите достъп до атрибути, които не съществуват в този обект!), вместо да подкласирате потребителския модел с AbstractUser?   -  person bgarcial    schedule 18.12.2015


Отговори (4)


В тази ситуация, особено ако искате да съхранявате различна информация за пациенти, медици и физиотерапевти, можете да създадете модел за всеки и да имате поле OneToOne за всеки към потребителския модел.

class Medic(models.Model):
    user = models.OneToOneField(User, primary_key=True)
    # other fields

class Physio(models.Model):
    user = models.OneToOneField(User, primary_key=True)
    # other fields

class Patient(models.Model):
    user = models.OneToOneField(User, primary_key=True)
    # other fields

По този начин можете да дадете различни разрешения/роли имплицитно в логиката на вашето приложение за всеки тип потребител (и все още да използвате групите и разрешенията, които Django предлага, ако имате нужда от тях за специални случаи, напр. ChiefMedical...).

Ще трябва да дефинирате някои методи за логиката на вашето приложение като

def user_is_patient(user):
     ...

Ако следвате този път, добра идея е да имате добри тестове, за да сте сигурни, че няма да получите неочаквани неща като потребител, който е медик и физиотерапевт...

Django ви позволява да класифицирате и потребителския модел. Под кориците ще направи същото като кода по-горе, така че вероятно е по-добре да го направите изрично, както е показано по-горе (по този начин е по-малко вероятно да имате достъп до атрибути, които не съществуват в този обект!)

Възползвайки се от предишното, следната схема може да бъде подходяща или може да бъде алтернатива за управление на потребителски роли (потребителски типове пациент, медицински и физиотерапевт)?

Схемата, която показвате, не е страхотна, защото ви кара да съхранявате информацията за всички типове потребители в една и съща таблица (и със същите полета). Например Медици и Физиотерапевти ще имат тип поле за кръвна група като Пациенти, което вероятно няма да бъде дефинирано.

Различните потребители ще бъдат запазени между таблицата Users и UserProfile. Това добра практика ли е в смисъл на мащабируемост? Моите таблици може да се сринат или моята база данни?

Не би трябвало да има проблеми с мащабируемостта с това решение (стига да нямате милиони нови записи всеки ден) и винаги можете да оптимизирате базата данни в следваща точка. Въпреки това ще трябва да се уверите, че приложението ви не приема „забранени“ записи (напр. потребители без профил на лекар, физиотерапевт или пациент)

Тук мога ли да видя създаването на групи? Например медицинска група и да им разпределите разрешения и да свържете тези разрешения с потребителите, които съставят групата? Това друга добра алтернатива ли е? Тази опция изглежда по-единична, въпреки че не знам дали потребителят може да извърши някои операции според груповите привилегии, които имат ... Не знам дали това мислене е правилно/правилно

Можете (трябва) да използвате системата за разрешения на Django, за да дадете разрешения на вашите потребители. Можете да ги използвате, за да дадете различни права на потребители от един и същи тип (например Медици, които имат повече разрешения от други... или имат групи за главни физиотерапевти...)

Django ви позволява да присвоявате разрешения на група.

Но не мисля, че групите могат да заменят персонализираните модели за всеки потребител, тъй като искате да съхранявате информация за тях. Наличието на персонализирани модели и групи би било излишно и би направило приложението ви по-трудно за поддръжка.

Изискванията ми за пациенти, медицински и физиотерапевтични потребители изискват изграждане на персонализиран потребителски модел?

Тази опция не би била чудесна (освен ако не е единствената ви опция), защото приложението ви няма да може да се използва повторно и може да имате проблеми и с някои пакети.

person Ire    schedule 13.12.2015

Можете да създадете персонализиран потребителски модел или не, във всеки случай можете да имате три отделни модела за съхраняване на подходящи данни, в зависимост от това дали потребителят е пациент, лекар, физиотерапевт или комбинация от тях.

Ако вашата схема за разрешения се определя единствено от ролята (пациент, лекар, физиотерапевт), тогава не е необходимо да използвате системата за разрешения на Django, защото знаете ролята(ите) на всеки потребител и можете, в най-лошия сценарий, да кодирате твърдо правила за оторизация.

person Lorenzo Peña    schedule 13.12.2015

Хвърлих един поглед на коментарите на въпроса и виждам някои проблеми:

(https://cldup.com/jxVsgfneGb.png)

Разбрах, че вашият потребителски модел не съвпада с оригиналния модел на данни, тъй като има get_medical_profile, get_patient_profile и get_physiotherapist_profile функции в потребителския модел, с това вие приемате, че всеки потребител може да има множество профили едновременно, което не е отразено нито в вашите профилни модели (медицински, пациентски и физиотерапевт), използващи OneToOneField, нито в оригиналния модел на данни на въпроса, това е важно нещо за абстракцията и класовата отговорност. Изискването (според модела по-долу) изглежда казва "един потребител може да има само един профил".

въведете описание на изображението тук

Така че.. Мисля, че това може да бъде решено по лесен и изчистен начин, не е необходимо да участвате в цялостната esquema за удостоверяване като групи и разрешения или добавяне на допълнителни атрибути към потребителския модел:

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    # common fields shared by medical, patient and physiotherapist profiles

class MedicalUser(models.Model):
    profile = models.OneToOneField(UserProfile)
    # medical fields here

class PatientUser(models.Model):
    profile = models.OneToOneField(UserProfile)
    # patient fields here

class PhysiotherapistUser(models.Model):
    profile = models.ForeignKey(UserProfile)
    # patient fields here

Както виждате, можете да имате профил, който съдържа общи полета, споделяни от всички профили. и всеки профил има определен модел.

Освен това можете да проверите дали потребителят е медицински чрез тази малка функция по-долу, след което, ако няма медицински профил, свързан с профила, тогава ще се предизвика изключение и това означава, че е неопределен профил:

def is_medical_profile(profile):
    try:
        profile.medical_user
        return True
    except:
        return False

Можете също да го използвате във вашите шаблони (като персонализиран етикет на шаблон) по следния начин:

{% if profile | is_medical_profile %}

С този подход не е необходимо да настройвате AUTH_USER_MODEL

Надявам се това да подобри вашето решение.


Допълнителни бележки:

Само в случай, че решите да имате персонализиран потребителски модел, настройте настройките.AUTH_USER_MODEL и го използвайте за външни ключове към User.

На част от текста на страхотна книга Две лъжички на Django казва:

От Django 1.5 нататък, официалният предпочитан начин за прикачване на ForeignKey, OneToOneField или ManyToManyField към потребител

Следователно моделът на вашия потребителски профил ще се промени, както следва:

from django.conf import settings
from django.db import models

class UserProfile(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL)

Да, изглежда малко странно, но това е съветът на официалните документи на Django.

person geoom    schedule 19.12.2015
comment
благодаря за препоръките и най-добрите практики :D. Подходът ти е страхотен! Въпреки че дори да посочвам връзка OneToOneField в моя модел на данни, потребителят може да има много профили (медицински, физиотерапевт и медицински). По-долу в публикацията направих някои тестове в cli - person bgarcial; 28.12.2015

@geoom @Ire @lorenzo-peña Създадох потребител през администраторския сайт на Django и проверих техните атрибути (is_medical, is_patient, is_physiotherapist) чрез обвивка на python

In [6]: User.objects.filter(username='agarcial').values('is_medical','is_patient','is_physiotherapist')

Out[6]: [{'is_physiotherapist': True, 'is_patient': True, 'is_medical': True}]

За момента в моите views.py правя, че потребител влиза само когато това е един от три типа потребители (медицински, пациент или физиотерапевт)

# Create your views here.


class ProfileView(LoginRequiredMixin, TemplateView):
    template_name = 'profile.html'
    def get_context_data(self, **kwargs):
        self.request.session['Hi'] = True
        context = super(ProfileView, self).get_context_data(**kwargs)
        is_auth = False
        name = None
        # Check if in the request goes the user
        user = self.request.user

        # Check about of possible cases (For now is one profile)
        if user.is_medical:
        #if self.request.user.is_authenticated():
            print (user.is_medical)
            is_auth = True
            profile=user.get_medical_profile()
            #name = self.request.user.username

            data = {
                'is_auth':is_auth,
                'profile':profile,
            }

            context.update({'userprofile':profile, 'data':data})
        elif user.is_patient:
            print (user.is_patient)
            is_auth=True
            profile=user.get_patient_profile()

            data = {
                'is_auth':is_auth,
                'profile':profile,
            }
            context.update({'userprofile':profile,'data':data})
        elif user.is_physiotherapist:
            print (user.is_physiotherapist)
            is_auth=True
            profile=user.get_physiotherapist_profile()

            data = {
                'is_auth':is_auth,
                'profile':profile,
            }
            context.update({'userprofile':profile,'data':data})
        return  context

    def get_userprofile(self):
        return self.request.user.userprofile

Ако проверя другите възможни комбинации (потребител пациент, лекар и физиотерапевт), това може ли да работи?

Мисля да създам групи за (Медици, пациенти, физиотерапевти) и обвързващи потребители за темата за оторизация, въпреки че трябва да прегледам други неща за процеса на оторизация, като django guardian например?

Какво ще кажете за това?

person bgarcial    schedule 28.12.2015