在django中将注册表单填写到数据库后如何存储用户选择的单选按钮值?

Posted

技术标签:

【中文标题】在django中将注册表单填写到数据库后如何存储用户选择的单选按钮值?【英文标题】:How to store the selected radio-button value of a user after filling the registration form into database in django? 【发布时间】:2019-06-19 14:35:47 【问题描述】:

我正在使用 django 为我的网站创建一个注册页面。注册表包含以下字段:用户名、电子邮件、密码、密码确认、用户类型。 user_type 可以是 'student' 或 'organisation',它是无线电选择类型。根据 user_type,用户只能执行分配给该类型的那些特定任务。所以我需要一种方法将他们的 user_type 存储到数据库中,然后检查它以让他们执行特定任务。我该如何解决这个问题?

Forms.py

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

USER_TYPE_CHOICES = (
('student', 'Student'),
('organization', 'Organization'),)

class UserRegisterForm(UserCreationForm):
email = forms.EmailField()
user_type = forms.ChoiceField(required=True,widget=forms.Radioselect, choices=USER_TYPE_CHOICES)

class Meta:
    model = User
    fields = ['username', 'email', 'password1', 'password2','user_type']

Views.py

from django.shortcuts import render, redirect
from django.contrib import messages
from .forms import UserRegisterForm


def register(request):
    if request.method == 'POST':
        form = UserRegisterForm(request.POST)
        if form.is_valid():
            form.save()
            username = form.cleaned_data.get('username')
            uType = form.cleaned_data.get('user_type')
            messages.success(request, 'Account created for , You may login now!'.format(username))
            return redirect('TakeTest-Home')
    else:
        form = UserRegisterForm()
    return render(request, 'users/register.html', 'form': form)

此应用的 Models.py 为空。

【问题讨论】:

user_type 是用户模型中的字段吗? 您应该创建一个包含用户选择的列表,然后将此列表存储在模型中的 user_type 字段中。 @DanielRoseman 是的 【参考方案1】:

由于,该表单字段的选择将是一个选定的字符串值,然后您可以将其作为字符字段存储在您的模型中:

所以,user_type = models.CharField()

如果您的选择与示例中的一样:

USER_TYPE_CHOICES = (
('student', 'Student'),
('organization', 'Organization'),)

但是,您可以为表单中的选项赋予整数值,例如:

choices=(
        (0,'Student'),
        (1,'Organization'),
)

因此,在您的模型中,您将其保存为 user_type = models.IntegerField()

由于每个用户只会保存一个值(一个选项),因此当您取回该字段值时,您只需根据代码中ifelse 的值定义任务和权限稍后。

如果您要从模型创建此表单,那么您可以在模型中非常相似地定义整个事物,包括选择值列表等等,但这不是重点问题。

因此,您的模型将如下所示:

class User(models.Model):
    username = models.CharField(max_length=150)
    email = models.EmailField(max_length=254)
    password1 = models.CharField(max_length=50)
    password1 = models.CharField(max_length=50)
    user_type = models.CharField(max_length=20)
    creation_date = models.DateTimeField(default=timezone.now)

    def __str__(self):
        return self.username

如果您愿意,您也可以在视图中将提交的表单值直接保存到数据库中:

from .forms import UserRegisterForm
from .models import User
# and so on imported

def register(request):
    if request.method == 'POST':

        username = request.POST.get('username')
        email = request.POST.get('email')
        password1 = request.POST.get('password1')
        password2 = request.POST.get('password2')
        user_type = request.POST.get('user_type')

        NewUser = User.objects.create(username = username, email = email, password1 = password1, password2 = password2, user_type = user_type)
        Try: 
            NewUser.full_clean(exclude=None, validate_unique=True)
            NewerUser.save()
            return HttpResponse('')
        except ValidationError as e:
            # Do something based on the errors contained in e.message_dict.
            # Display them to a user, or handle them programmatically.
            pass

        # you can send back messages here too    
        return HttpResponse('whatever')
    else:
        form = UserRegisterForm()
        return render(request, 'users/register.html', 'form': form)

当然,您可以像在问题中那样使用普通的表单保存方法来保存它,我只是不想从您的问题中重复您的代码。

重点在于您的问题,您可以将所选的 user_type 值保存为 Charfield,也可以将所选的值保存为模型中的 IntegerField。在数据库中,每个用户只有一个值。然后您可以稍后使用该值。

更清楚一点的是,在每个注册用户的 User 表中都有该值之后,您可以根据 user_type 值以任何方式重定向任务:

def Usertask_sorting(task1, task2, username):
    Task1 = task1
    Task2 = task2
    Username = username
    field_name = 'user_type'
    obj = User.objects.get(username=Username)
    user_type_value = getattr(obj, field_name)
    if user_type_value == 'Student':
        # let them do task1 or whatever
        return redirect('student_form')
    elif user_type_value == 'Organization':
        # let the user do task2 something else
        return redirect('organization_form')
    else :
        # the user has no valid user_type set
        return redirect('profile_form')

我希望这可以给你一些问题的方向。

更新 - 仅针对自定义用户模型提供一些有用的建议

现在上面的内容很好并回答了原始问题,但是我向@Kiran 承诺,我会为他的自定义用户结构提供一些额外的有用建议。由于在实时环境中创建一个名为 User 的模型并不幸运,因为 Django 已经有一个 User Model,因此可能会导致冲突。

相反,我们所做的是从 AbstractModel 类创建我们自己的用户模型,该类使用 Django 用户模型的所有优点。最好在一个新的 Django 项目中尝试和实践整个事情!

但在此之前,我们创建一个 userType 模型,因为最好将 user_types 放在一个表中,而不是在我们的模型或表单中硬编码,然后我们可以更轻松地添加或删除 user_types。由于我们想在我们的自定义用户模型中使用这个模型的值来选择 user_type:

from django.db import models

class userType(models.Model):

    name = models.CharField(max_length=50)

    def __str__(self):
        return self.name

然后我们只运行migrate,然后我们继续下一步:

通过创建我们的自定义用户模型

from django.db import models
from django.contrib.auth.base_user import AbstractBaseUser

class OurUser(AbstractUser):

    # we get the usertype choice values from the userType table and creating a list of that
    all_user_types = userType.objects.values()
    USER_TYPE_CHOICES = [(d['id'], d['name']) for d in all_user_types]

    chosen_user_type = models.PositiveSmallIntegerField(choices=USER_TYPE_CHOICES, null=True, verbose_name='User type')

然后我们将从用户模型创建表单:

from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.forms import AuthenticationForm
from django import forms
from .models import OurUser

class UserRegistration(UserCreationForm):
    class Meta:
        model = OurUser
        fields = ['username', 'email','chosen_user_type',]

然后我们为注册创建我们的视图

from django.shortcuts import render, redirect
from django.http import HttpResponseRedirect, HttpResponse, HttpRequest
from django.urls import reverse
from django.views import View
from .models import OurUser
from django.template import loader
from django.contrib.auth import login, authenticate
# from django.contrib.auth.forms import UserCreationForm
from .forms import UserRegistration
from .models import OurUser

def signup(request):
    if request.method == 'POST':
        form = UserRegistration(request.POST)
        if form.is_valid():
            # form.save()
            username = form.cleaned_data.get('username')
            email = form.cleaned_data.get('email')
            raw_password = form.cleaned_data.get('password1')
            chosen_user_type = form.cleaned_data.get('chosen_user_type')
            newUser = OurUser.objects.create_user(username=username, email=email, password=raw_password, chosen_user_type=chosen_user_type)
            newUser.save()
            # user = authenticate(email=email, password=raw_password) # authenticate not needed here
            login(request, user)
            return HttpResponseRedirect(reverse('myappname:index'))
    else:
        form = UserRegistration()
    return render(request, 'myappname/signup.html', 'form': form)

最后我们不必忘记在admin.py注册我们的模型

from django.contrib import admin
from .models import OurUser, userType

# Register your models here.
admin.site.register(OurUser)
admin.site.register(userType)

我们也不必忘记在settings.py中定义我们的自定义用户模型身份验证

AUTH_USER_MODEL = 'myappname.OurUser'

urls.py 中,我们必须为我们的注册表单 提供一个url 路径,例如:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('signup', views.signup, name='signup'),
]

还有我们模板文件夹中的signup.html

% extends 'myappname/base.html' %

% block content %
  <h2>Sign up</h2>
  <form method="post">
    % csrf_token %
     form.as_p 
    <button type="submit">Sign up</button>
  </form>
% endblock %

最后我们只需要运行migrate,我们应该去我们网站的管理员并在我们的userType表中创建一些用户类型,这些用户类型将用于我们的自定义注册表单作为选择。

所以我希望它能更清楚地说明这个问题。然后我们还必须弄清楚与我们的用户类型相关的权限等。干杯。 ;)

【讨论】:

非常感谢您花时间解释它!我现在已经明白了,我相信它会对我有很大帮助! :) 如果我从 django 的管理页面中删除一个用户,它不会反映在数据库表中。我该如何解决? @Kiran - 该项目应该从数据库中实际删除。如果您通过管理员删除它。您是否可以提供有关此问题的更多信息? @Kiran - 我再次阅读了您的问题并更好地理解了它。我在这里可以想象的问题是您将模型定义为用户,这不是您自定义模型的幸运名称,因为 Django 已经默认拥有用户表和用户模型,所以这里可能会有一点冲突。请根据您的情况检查一下,然后给我一些反馈。 @Kiran - 在我的回答中,模型只是一个示例,我不会以这种方式使用该名称。如果您需要,我可以通过一些其他有用的东西和关于用户管理的真实示例以及如何向用户添加不同的组来扩展我的答案。【参考方案2】:

首先,您需要知道,django 中的选择只是多对多字段。

所以你需要在models.py中声明它应该如下:

class Choices(models.Model):
  description = models.CharField(max_length=100)

class UserProfile(models.Model):
  user = models.ForeignKey(User, blank=True, unique=True, verbose_name='profile_user')
  choices = models.ManyToManyField(Choices)
  def __unicode__(self):
    return self.name

现在你可以根据它来改变你的form.py了。

在views.py中保存如下表单数据:

from django.shortcuts import render, redirect
from django.contrib import messages
from .forms import UserRegisterForm


def register(request):
    if request.method == 'POST':
        form = UserRegisterForm(request.POST)
        if form.is_valid():
            form.save()
            messages.success(request, 'Account created for , You may login now!'.format(username))
            return redirect('TakeTest-Home')
    else:
        form = UserRegisterForm()
    return render(request, 'users/register.html', 'form': form)

我希望它会有所帮助。

【讨论】:

你能帮我理解 django 中选择的“多对多字段”是什么意思吗?

以上是关于在django中将注册表单填写到数据库后如何存储用户选择的单选按钮值?的主要内容,如果未能解决你的问题,请参考以下文章

Django 会话与浏览器本地存储

在用户注册之前保存 django 模型表单数据

毕业设计——Django项目网页刷新表单重复提交问题

注册表单不起作用(CSRF 令牌丢失或不正确。) django

在 django 中将一个视图函数输出到另一个视图函数

如何在 django 中查找会话是不是已过期