Как предопределить значение внутри модели/формы в Django?

Я создаю простое приложение, которое позволяет пользователям создавать группы. Когда пользователь создает группу, она имеет следующие поля:

  • имя
  • desc
  • inviteKey - я хочу, чтобы это поле было скрыто и генерировало 10-символьный код, а затем отправляло его.

Мои модели:

class Group(models.Model):
    groupName = models.CharField(max_length=100)
    description = models.CharField(max_length=255)
    inviteKey = models.CharField(max_length=255)


class Members(models.Model):
    userId = models.ForeignKey(User, on_delete=models.CASCADE)
    groupId = models.ForeignKey(Group, on_delete=models.CASCADE)
    isAdmin = models.BooleanField(default=False)

Форма:

class GroupForm(forms.ModelForm):
    groupName = forms.CharField(label='Nazwa grupy', max_length=100)
    description = forms.CharField(label='Opis', max_length=255)
    inviteKey: forms.CharField(label='Kod wstępu')

    class Meta:
        model = Group
        fields = ['groupName', 'description', 'inviteKey' ]

Вид:

def createGroup(request):
    if request.method == "POST":
        form = GroupForm(request.POST)
        if form.is_valid():
            form.save()
            messages.success(request, f'Group created')
            return redirect('/')
    else:
        inviteKey = generateInviteKey()
        form = GroupForm(initial={'inviteKey': inviteKey})

    return render(request, 'group/createGroup.html',{'form': form})

Сейчас у меня есть форма и inviteKey виден и редактируется. Я хочу, чтобы этот ключ был виден, но не редактировался.

Form

На мой взгляд, лучший способ сделать это - установить значение по умолчанию для ключа приглашения в вашей model, таким образом, токен будет создан "в фоновом режиме" с уникальным ключом, но мы можем пойти дальше.

Например :

import uuid
token = models.UUIDField(
    default=uuid.uuid4,
    unique=True,
    editable=False,
)

Таким образом, вы будете уверены, что токен уникален (UUID уникален по замыслу, но все же), вы не сможете его отредактировать, так что неправильный токен не может возникнуть, и, наконец, каждый объект получит уникальный токен без какой-либо работы с вашей стороны.

Я использую UUID, потому что он рекомендован Django согласно Документации для токена и уникального идентификатора.

Примечание : Если вы установите UUID со значением по умолчанию, вы не сможете получить его до создания объекта, в зависимости от вашего использования вы можете захотеть установить его в форме (см. ответ ниже).

Вы можете сделать поле неактивным, так:

class GroupForm(forms.ModelForm):
    groupName = forms.CharField(label='Nazwa grupy', max_length=100)
    description = forms.CharField(label='Opis', max_length=255)
    inviteKey = forms.CharField(label='Kod wstępu', disabled=True)

    class Meta:
        model = Group
        fields = ['groupName', 'description', 'inviteKey' ]

Это также не позволит пользователю сфабриковать POST-запрос, содержащий другой ключ приглашения.

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

def createGroup(request):
    if request.method == 'POST' and 'inviteKey' in request.session:
        inviteKey = request.session['inviteKey']
        form = GroupForm(request.POST, initial={'inviteKey': inviteKey})
        if form.is_valid():
            form.save()
            messages.success(request, f'Group created')
            return redirect('/')
    else:
        request.session['inviteKey'] = inviteKey = generateInviteKey()
        form = GroupForm(initial={'inviteKey': inviteKey})

    return render(request, 'group/createGroup.html',{'form': form})

Вероятно, вы также захотите сделать ваше поле inviteKey уникальным, чтобы предотвратить создание нескольких групп с одинаковыми inviteKey:

class Group(models.Model):
    groupName = models.CharField(max_length=100)
    description = models.CharField(max_length=255)
    inviteKey = models.CharField(max_length=255, unique=True)
Вернуться на верх