Правильный дизайн в Django для обработки форм и представлений в зависимости от типа пользователя - PullRequest
2 голосов
/ 12 мая 2019

Проблема

Я пишу приложение на Django, которое связывает студентов с репетиторами.Существует три основных модели: Student, Tutor и Coordinator.

Проблема в том, что сам по себе веб-сайт довольно похож на все три типа моделей, но каждая немного отличается в зависимости от того, что они действительно делают или видят.

Например, все триТипы пользователей могут забронировать класс через BookClassForm.Тем не менее, Coordinator может назначить наставника и ученика, в то время как наставник и ученик не могут.Или, например, Coordinator может видеть все классы от всех учеников и преподавателей в представлении календаря, в то время как ученик видит только его классы.

В целом это означает, что я должен написатьтри отдельные формы или одна форма, которая делает некоторые входные данные необязательными для каждого типа пользователя?Я пишу три шаблона или один шаблон, где я помещаю логику для каждого типа пользователя?Я пишу три представления, которые обрабатывают каждый тип пользователя или один основной вид?Пишу ли я три приложения для каждого типа пользователей или одно основное приложение?

Я заканчиваю этим действительно большим приложением с большим количеством просмотров и повторяющимся кодом, и я не знаю, какой правильный курсдействия.


Я попробовал несколько вариантов, чтобы решить эту проблему настолько просто, насколько смогу:

Вариант 1

Первый вариант довольно наивный,Я поддерживаю только один urls.py файл и делаю логику в представлении.Что-то вроде:

# views.py
def classes_view(request):
   if request.user.is_superuser:
     # a coordinator
     return render(request, "classes.html", {'classes': Class.objects.all()})
   try:
      if request.user.tutor:
        return render(request, "classes.html", {'classes': Class.objects.filter(tutor=request.user.tutor))
    except Tutor.DoesNotExist:
        return render(request, "classes.html", {'classes': Class.objects.filter(student=request.user.student))

Проблема в том, что я пишу этот стандартный код для десятков просмотров.

Вариант 2

Разделите проект на три приложения(студент, репетитор, координатор) и обрабатывать мнения отдельно.Боюсь, что эта опция приведет к многократному дублированию кода, но я могу ошибаться.Еще одно неудобство, которое я вижу, это то, что происходит, когда три приложения хотят взаимодействовать с четвертым распространенным приложением?

Скажем, например, я создаю приложение notifications, которое обрабатывает всю логику и модели для уведомлений в приложении.У него будет urls.py, например:

urlpatterns = [
    url(r'delete-notification/(?P<pk>\d+)$', NotificationDelete.as_view(), name='delete-notification'),
    url(r'notification/(?P<pk>\d+)$', NotificationView.as_view(), name='notifications'),
]

Теперь, если я хочу подключить его как к координатору, так и к студенту, мне нужно добавить к обоим следующим элементам:

# coordinator/urls.py
urlpatterns = [
    url(r'^notifications/', include('notifications.urls')),
    url(r'^tutors/', TutorsView.as_view(), name='tutors'),
]

# student/urls.py
urlpatterns = [
    url(r'^notifications/', include('notifications.urls')),
    url(r'^my-classes/', ClassesView.as_view(), name='classes'),
]

Но что тогда, если я хочу добавить логику в приложение уведомлений, которое зависит от типа пользователя?Что если я хочу мягко удалить уведомления для Coordinator с и жестко удалить уведомления для Student с?Куда бы я положил логику там?Я чувствую, что приложение уведомлений не зависит от всего этого.


Не знаю, я очень растерялся.

Любая помощь очень ценится.

Спасибо.

1 Ответ

0 голосов
/ 12 мая 2019

Создайте три группы пользователей, назначьте соответствующих пользователей в соответствующие группы и предоставьте им необходимые разрешения.

От имени вашего вопроса будет 3 группы пользователей, а именно: Репетитор, Студент и Координатор

Вво время регистрации проверьте, является ли пользователь студентом, репетитором или координатором.

models.py

from django.contrib.auth.models import AbstractUser

checking_choices = (
    ('student', 'Student'),
    ('tutor', 'Tutor'),
    ('coordinator', 'Coordinator'),
)

class User(AbstractUser):
    student_or_tutor_coordinator = models.CharField(max_length=12, choices=checking_choices, blank=True)

Приведенная выше модель добавит дополнительное поле во время регистрации пользователя

forms.py

from .model import User
from django.contrib.auth.forms import UserCreationForm


class SignupForm(UserCreationForm):
    class Meta:
        model = User
        fields = ('username', 'email', 'password1', 'password2', 'student_or_tutor_coordinator')

Регистрация функции просмотра и добавление пользователей от имени опции, которую они используют


def signup(request):
    User = get_user_model()
    if request.method == 'POST':
        form = SignupForm(request.POST)
        if form.is_valid():
            checker = form.data.get('student_or_tutor_coordinator')
            if (checker == 'student'):
                 user = form.save(commit=False)
                 user.save()
                 group = Group.objects.get(name='Student')
                 user.groups.add(group)

            elif (checker == 'tutor'):
                 user = form.save(commit=False)
                 user.save()
                 group = Group.objects.get(name='Tutor')
                 user.groups.add(group)     

            if (checker == 'coordinator'):
                 user = form.save(commit=False)
                 user.save()
                 group = Group.objects.get(name='Coordinator')
                 user.groups.add(group)

    else :
        form = SignupForm()
    return render(request, 'regform.html', {'form': form})   

Создание панели мониторинга и панели мониторинга ввремя входа в систему с группами пользователей и отображения соответствующего шаблона.


def dashboard(request):

    Student = Group.objects.get(name='Student')
    Tutor = Group.objects.get(name='Tutor')
    Cooridnator = Group.objects.get(name='Coordinator')

    if request.user in Student.user_set.all():
        ...
        ...
        #yourcode
        return render(request, 'studenttdashboard.html')

    elif request.user in Tutor.user_set.all():
        ...
        ...
        #yourcode
        return render(request, 'tutordashboard.html')

    elif request.user in Coordinator.user_set.all():
        ...
        ...
        #yourcode
        return render(request, 'coordinatordashboard.html')

Каждая группа может быть назначена с разрешениями для моделей на административном портале django.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...