Pytanie Konfigurowanie dwóch różnych typów użytkowników w Django 1.5 / 1.6


Uwaga - jest to zaktualizowana wersja moje oryginalne pytanie na ten temat, ale zasługuje na to, by zapytać ponownie o zmianę sposobu, w jaki Django zajmuje się użytkownikami i uwierzytelnianiem.

Pracuję nad stroną z dwoma różnymi użytkownikami - nazwijmy to Customers i Store Owners. Oba rejestrują się na stronie, ale mają bardzo różną funkcjonalność. Customers po prostu mają jeden profil i mogą robić zakupy w sklepach, które im się podobają. Store Owners mieć jedno konto, ale może mieć dostęp do wielu sklepów, a każdy sklep może mieć wiele Store Owners.

Dokładne szczegóły modeli nie mają znaczenia, ale dwa typy użytkowników wymagałyby bardzo różnych dziedzin. Modele idealnie wyglądałyby tak:

Customer
  email (username)
  password
  name
  address
  time_zone
  preferred_shipping
  favorite_stores (many-to-many field)
  ...

Store Owner
  email (username)
  password
  name
  balance
  stores_owned (many-to-many field on Stores)
  stores_managed (many-to-many field on Stores)
  ...

Początkowo, gdy Django miał kiepską niestandardową obsługę, miałem UserProfile klasa z dodatkowymi polami z a OneToOne na User, a następnie dodatkowe Customer i StoreOwner klasy, które były OneToOne na UserProfile. To nie działało zbyt dobrze.

Biorąc pod uwagę zmiany w Django 1.5 / 1.6, staram się wymyślić najlepszy sposób na ustrukturyzowanie tego. W tej chwili mam następujące:

class CustomerUser(AbstractBaseUser):
    ...

class StoreOwnerUser(AbstractBaseUser):
    ...

Ale ponieważ istnieją dwa typy użytkowników, nie mogę ich ustawić AUTH_USER_MODEL tylko do jednego z nich.

Jaki jest najlepszy sposób strukturyzacji, aby móc mieć dwa różne typy użytkowników z różnymi polami, nie powodując żadnych problemów z uwierzytelnianiem użytkownika, tworzeniem użytkownika ani administrowaniem?

Ponadto, w jaki sposób będę w stanie stwierdzić z samego logowania, czy ten użytkownik jest użytkownikiem CustomerUser lub StoreOwnerUser?


11
2017-12-26 04:20


pochodzenie


Możesz utworzyć użytkownika podstawowego, dodać flagę typu boolean, która oznacza, czy użytkownik jest właścicielem klienta lub sklepu i dołączyć inny model, który jest profilem, przy użyciu relacji jeden-do-jednego. - user1876508
Minął prawie rok, odkąd o to pytano, ale znajduję się w podobnej sytuacji. Pytanie: jakie podejście podjąłeś w końcu? Czy bierzesz pod uwagę przypadek, w którym właściciel sklepu może chcieć zarejestrować się jako klient (używając tego samego adresu e-mail)? Jak twój projekt zaspokoi tę sprawę? Na koniec, czy kiedykolwiek rozważałeś posiadanie oddzielnych widoków logowania dla właścicieli i klientów (co może pomóc w łatwym rozróżnieniu typu użytkownika wpisującego się na serwer)? - Hari Mahadevan


Odpowiedzi:


Wygląda na to, że typ użytkowników ma kilka typowych funkcji i nietypowych funkcji. Jeśli w typach użytkowników istnieją typowe funkcje, których domyślny model użytkownika Django nie obsługuje po rozpakowaniu, należy go podklasować bezpośrednio.

Dodawanie dodatkowych, nietypowych funkcji do typów użytkowników najlepiej wykonywać nie poprzez podklasy, ale za pomocą profilu. Moją przesłanką jest to, że twoje uwierzytelnienie dla tych typów użytkowników zasadniczo się nie zmienia, ale szczegóły dotyczące użytkownika zależą od typu użytkownika. Aby to osiągnąć, utwórz osobny model z tymi szczegółami i odwołaj się do klasy użytkownika jako relacji OneToOne / ForeignKey (w zależności od projektu).

Można wprowadzić modyfikacje procesu tworzenia użytkownika, aby określić typ użytkownika, jaki powinien być, i ustawić powiązany OneToOneField / ForeignKey (w zależności od projektu) do odpowiedniego modelu klienta.

Robiąc to w ten sposób, powinieneś mieć tylko jednego AUTH_USER_MODEL, i powinieneś być w stanie obsłużyć szczegóły dla różnych typów klientów.


5
2017-12-26 04:29



Dzięki - to ma sens. Ale skąd miałbym się dowiedzieć, czy użytkownik logujący się jest zalogowany StoreOwner lub Customer? Czy miałbym w bazie? UserProfile klasa A storeowner_or_customer pole, czy coś w tym stylu? - jdotjdot
Coś w tym stylu. UserProfile musiałby być dostępny dla użytkownika i byłby czymś, co ustawiałbyś za każdym razem, gdy użytkownik jest tworzony. Sugerowałbym, aby dwa modele profili były dwoma typami użytkownika (StoreOwner / Customer), a następnie można dodać pole typu "type" do modelu użytkownika, do którego odniesienia odnoszą dwa typy użytkowników za pośrednictwem relacji OneToOne. W swoim kodzie najpierw sprawdzasz typ (np. User_obj.type == "Customer" lub coś podobnego), a jeśli true, możesz uzyskać dostęp do powiązanych szczegółów bezpośrednio user_obj.customer.address. - tsurantino


Jak najlepiej to zorganizować, aby móc mieć dwa   różne rodzaje użytkowników z różnymi polami, bez powodowania mnie   problemy z uwierzytelnianiem użytkownika, tworzeniem użytkownika lub adminem?

W rzeczywistości masz tylko jeden typ użytkownika. Tylko niektórzy użytkownicy mają określone właściwości, a inni nie. Zastanów się, jak django ma "użytkowników" i "adminów". Są to przykłady ten sam model, ale z różnymi właściwościami i uprawnieniami.

Powinieneś podejść do niego w podobny sposób. Masz jeden model użytkownika dla całej aplikacji. Możesz ustawić właściwości / metody w swojej niestandardowej klasie użytkownika, aby zidentyfikować flagi ustawione przez użytkownika (które określałyby "typ" użytkownika).

Ponadto, w jaki sposób będę mógł powiedzieć, od samego logowania, czy ten użytkownik jest   za CustomerUser lub StoreOwnerUser?

Możesz użyć user_passes_test decorator, który przyjmuje argument będący nazwą funkcji i przetwarza widok tylko wtedy, gdy funkcja zwraca wartość prawdy.


3
2017-12-26 04:38



Bardzo podoba mi się ten pomysł, ale czy nie skończyłoby się to na tym, że mam duży zbiór nieużywanych pól w tym modelu? Czy są tam jakieś implikacje, szczególnie w przypadku generowania formy? - jdotjdot
Nie, zwłaszcza jeśli poprawnie używasz odwrotnych relacji modeli. Na przykład nie potrzebujesz stores_owned i stores_managed pola, ponieważ te informacje można pobrać za pomocą ORM. Na przykład możesz mieć metodę w User to wróci self.stores_set.count() dla "zarządzanych sklepów"; miałbyś tę metodę w modelu, gdybyś wyświetlił ją w adminie jako część widoku listy modeli, w przeciwnym razie byłaby to wartość, która byłaby gdzieś w pamięci podręcznej. - Burhan Khalid


  1. Utwórz BaseUser, który rozszerza Podstawowego Użytkownika Django
  2. Utwórz dwie klasy podrzędne nazwany CustomerUser i StoreOwnerUser, który rozszerza BaseUser

    from django.db import models
    from django.contrib.auth.models import AbstractUser
    
    class BaseUser(AbstractUser):
        # all the common fields go here, for example:
        email = models.EmailField(max_length=10,unique=True)
        name = models.CharField(max_length=120)
    
    class StoreOwnerUser(BaseUser):
        # All Store Owner specific attribute goes here
        balance = models.some_balance_field()
        stores_owned = models.some_stores_owned_field()
    
        class Meta:
        verbose_name = 'Store Owner'
    
    class CustomerUser(BaseUser):
        # All Customer specific attribute goes here
        customer_id = models.CharField(max_length=30, unique=True)
        address =  models.some_address
        time_zone = models.something...
        ...
    
        class Meta:
            verbose_name = 'Customer'
    

1
2017-08-07 08:30



Co zostanie określone jako AUTH_USER_MODEL? Również w momencie logowania: user = authenticate(username = username, password = password). Z którego tabeli (CustomerUser lub StoreOwnerUser) byłby authenticate sprawdzanie funkcji z? - Sibtain
możesz wykonać tę implementację stackoverflow.com/questions/30495979/... - Saber Solooki