Нахожусь ли я на правильном пути к внедрению нескольких родных и изучаемых языков в форму регистрации пользователя?

Я пытаюсь создать простую цифровую платформу для обучения, похожую на флэшкарту, где пользователь может выбрать свой родной язык и языки, которые он изучает. Как вы можете себе представить, могут быть люди, которые говорят на нескольких языках на родном уровне, и я уверен, что есть люди, которые изучают несколько языков. Чтобы обрисовать мою проблему, предположим, что пользователь изучает 20 языков и может свободно говорить на 3 языках.

В перспективе я хотел бы использовать языки пользователя (как изучаемые, так и родные) и использовать их в качестве фильтрации выпадающего списка. Например, они могут прикрепить один язык к карточке, но в выпадающем списке выбора языка будут показаны все изученные языки.

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


(Жестко закодировано) Ужасная реализация

Я знаю, что могу реализовать это, просто перечислив кучу повторяющихся полей, а затем преобразовать CharField в поле Select через choices:

class User(AbstractUser):
    native_language1 = ...
    native_language2 = ...
    native_language3 = ...
    studying_language1 = ...
    .... 
    native_language20 = ...

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


(Потенциальное решение) Использование ArrayField

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

users\models.py

...
from django.contrib.postgres.fields import ArrayField
from django.conf.global_settings import LANGUAGES


class User(AbstractUser):
    """
    Default custom user model for LangCorrect.
    If adding fields that need to be filled at user signup,
    check forms.SignupForm and forms.SocialSignupForms accordingly.
    """

    #: First and last name do not cover name patterns around the globe
    name = CharField(_("Name of User"), blank=True, max_length=255)
    first_name = None  # type: ignore
    last_name = None  # type: ignore

    #: User languages
    native_languages = ArrayField(
        CharField(choices=LANGUAGES, max_length=10)
    )
    studying_languages = ArrayField(
        CharField(choices=LANGUAGES, max_length=10)
    )

    def get_absolute_url(self):
        """Get url for user's detail view.

        Returns:
            str: URL for user detail.

        """
        return reverse("users:detail", kwargs={"username": self.username})

Выбор языка не отображается и это просто пустое поле CharField.

Admin

@admin.register(User)
class UserAdmin(auth_admin.UserAdmin):

    form = UserAdminChangeForm
    add_form = UserAdminCreationForm
    fieldsets = (
        (None, {"fields": ("username", "password")}),
        (_("Personal info"), {"fields": ("name", "email")}),
        (
            _("Languages"),
            {
                "fields": (
                    "native_languages",
                )
            },
        ),
        (
            _("Permissions"),
            {
                "fields": (
                    "is_active",
                    "is_staff",
                    "is_superuser",
                    "groups",
                    "user_permissions",
                ),
            },
        ),
        (_("Important dates"), {"fields": ("last_login", "date_joined")}),
    )
    list_display = ["username", "name", "is_superuser"]
    search_fields = ["name"]

Так что мне интересно, на правильном ли я пути с использованием ArrayField, или я должен использовать что-то другое?

Вернуться на верх