Django вопрос по проверке переменной в модели

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

Модель ключа отдельную создал присваивается команде, изначально был ключ внутри тимы, но решил вынести его в свою модель

models.py

from django.db import models
from django.contrib.auth.models import User
from slugify import slugify
from django.urls import reverse


class BaseModel(models.Model):
    objects = models.Manager()

    class Meta:
        abstract = True


class Role(BaseModel):
    name = models.CharField('Роль', max_length=30, blank=True, null=True)

    def __str__(self):
        return self.name


class Profile(BaseModel):
    user = models.OneToOneField(
        User, on_delete=models.CASCADE, null=True, blank=True
    )
    nickname = models.CharField(max_length=30, unique=True, null=True)
    team = models.ForeignKey('Team', on_delete=models.SET_NULL, blank=True, null=True)
    role = models.ForeignKey(Role, on_delete=models.SET_NULL, blank=True, null=True)

    def save(self, *args, **kwargs):
        super(self.__class__, self).save(*args, **kwargs)
        if self._state.adding is True:
            Profile.objects.create()

    def __str__(self):
        return self.nickname

    class Meta:
        verbose_name = "Автор"
        verbose_name_plural = "Авторы"


class Team(BaseModel):
    name = models.CharField('Название', max_length=50)
    tag = models.CharField('Тег', max_length=16, unique=True)
    # key = models.CharField('Код вступления', max_length=20, null=True, blank=True, unique=True)
    slug = models.SlugField(unique=True, blank=True, null=True)

    def __str__(self):
        return f'{self.name} [{self.tag}]'

    def get_absolute_url(self):
        return reverse("team_detail", kwargs={"slug": self.slug})

    def save(self, *args, **kwargs):
        self.slug = slugify(self.name)
        super(Team, self).save(*args, **kwargs)

    class Meta:
        verbose_name = "Команда"
        verbose_name_plural = "Команды"


class Key(BaseModel):
    team = models.OneToOneField(Team, on_delete=models.SET_NULL, null=True, blank=True)
    key = models.CharField('Код вступления', max_length=20, null=True, blank=True, unique=True)

    def __str__(self):
        return self.key

И вот обновленная forms

forms.py

from django import forms
from django.contrib.auth.models import User
from django.forms import TextInput, Textarea, FileInput, IntegerField
from django.forms import TextInput, Textarea, FileInput, Select

from .models import *


class CreateKeyForm(forms.ModelForm):
    class Meta:
        model = Key
        fields = {
            'team', 'key'
        }


class JoinTeamForm(forms.ModelForm):
    key = forms.CharField(label='key', max_length=20)

    class Meta:
        model = Key
        fields = {'key'}


class CreateTeamForm(forms.ModelForm):
    class Meta:
        model = Team
        fields = {
            'name', 'tag'
        }

Ну и html в котором вводится код.

<form action="{% url 'join_team' team.id %}" method="post">
    {% csrf_token %}
    <label for="key">Key: </label><br>
    <input id="key" type="text" name="key" value="">
    <button type="submit">Присоедениться</button>
</form>

вот urls

urls.py

urlpatterns = [
    path('home', CreateTeam.as_view(), name='home'),
    path('teams', TeamView.as_view(), name='teams'),
    path('teams/<slug:slug>/', TeamDetail.as_view(), name='team_detail'),
    path('join/<int:pk>/', JoinTeam.as_view(), name='join_team'),
]

Весь views

from django.conf import settings
from django.contrib.auth import authenticate, login, get_user_model
from django.http import HttpResponseRedirect, Http404, HttpResponse
from django.shortcuts import render, redirect, resolve_url
from django.utils.http import url_has_allowed_host_and_scheme
from django.views.generic.base import View
from django.views.generic import DetailView, ListView
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from django.views.decorators.csrf import csrf_exempt

from .models import *
from .forms import *
import random
import string

"""
Создание случайной буквенно-цифровой строки
"""


# def generate_alphanum_random_string(20):
#     letters_and_digits = string.ascii_letters + string.digits
#     rand_string = ''.join(random.sample(letters_and_digits, length))

def generate_alphanum_random_string(length):
    letters_and_digits = string.ascii_letters + string.digits
    rand_string = ''.join(random.sample(letters_and_digits, length))
    return str(rand_string)


# Create your views here.

class TeamView(ListView):
    model = Team
    queryset = Team.objects.all()
    # template_name = 'team/team_list.html'


class TeamDetail(DetailView):
    model = Team
    slug_field = 'slug'


class CreateTeam(LoginRequiredMixin, View):

    def get(self, request, *args, **kwargs):
        form = CreateTeamForm(request.POST)
        context = {'form': form}
        return render(request, 'team/home.html', context)

    def post(self, request, *args, **kwargs):
        print(request.POST)
        profile = request.user.profile
        if request.method == 'POST':
            form = CreateTeamForm(request.POST)
            key_form = CreateKeyForm(request.POST)
            role = Role.objects.get(id=1)
            if form.is_valid():
                key = key_form.save(commit=False)
                # form = form.save(commit=False)
                # form.key = generate_alphanum_random_string(20)
                # form.save()
                team = form.save()
                key.team = team
                key.key = generate_alphanum_random_string(20)
                key.save()
                profile.team = team
                profile.role = role
                profile.save()
                return redirect('home')
            return redirect('home')


class JoinTeam(LoginRequiredMixin, View):

    def get(self, request, pk):
        print(f'post:{request.POST}, get:{request.GET}')
        form = JoinTeamForm(request.POST or None)
        team = Team.objects.get(id=pk)
        context = {'form': form,
                   'team': team
                   }
        return render(request, 'team/team_detail.html', context)

    def post(self, request, pk):
        print(f'post: {request.POST} team_id: {Team.objects.get(id=pk).key}')
        profile = request.user.profile
        error_msg = 'Неверный код'
        if request.method == 'POST':
            form = JoinTeamForm(request.POST)
            role = Role.objects.get(id=2)
            team = Team.objects.get(id=pk)
            if form.is_valid():
                key = form
                if key == team.key.key:
                    profile.team = team
                    profile.role = role
                    profile.save()
                    # return redirect(team.get_absolute_url())
                else:
                    return HttpResponse(error_msg)
            return redirect(team.get_absolute_url())


Ответы (1 шт):

Автор решения: Andrew Holovko

Предлагаю использовать form.Forms вместо forms.ModelForm в формах, где вы не хотите сразу вносить или изменять данные в БД, последняя это и делает.

Вот ваша готовая форма:

class JoinTeamForm(forms.Form):
    key = forms.CharField(label='key', max_length=20)

    class Meta:
        model = Key
        fields = {'key'}

Далее пример метода, который обрабатывает запрос от формы.

    def post(self, request, team_id):
        if request.method == 'POST':
            form = JoinTeamForm(request.POST)
            if form.is_valid() and request.user.is_authenticated:
                key = form.cleaned_data['key']  # get key from form
                db_key = Key.objects.filter(key=key).first()  # get key from db
                role = Role.objects.get(id=1)
                if db_key and role:
                    profile = Profile(
                        role_id=role.id,
                        team_id=db_key.team_id,
                        user_id=request.user.id
                    )
                    profile.save()
            return redirect('join_team', team_id=team_id)

Я немного упростил её, но суть вы поймёте. Проверено, всё работает.

→ Ссылка