问题扩展django用户模型
我有一个网站,用户应该能够注册为“工人”或“客户”,一个超级模型类型的网站。我创建了两个模型WorkerProfile
和CustomerProfile
以及这两种表单,但是每次我提交客户或工作者表单时,新用户都会在http://127.0.0.1:8000/admin/的数据库中同时存入客户个人资料和工作人员个人资料,我如何防止这种情况发生发生了什么?问题扩展django用户模型
models.py:
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
class WorkerProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
university = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
role = models.CharField(max_length = 10, default = 'USER')
def __str__(self):
return self.user.username
@receiver(post_save, sender=User)
def create_worker_profile(sender, instance, created, **kwargs):
if created:
WorkerProfile.objects.create(user=instance)
@receiver(post_save, sender=User)
def save_worker_profile(sender, instance, **kwargs):
instance.workerprofile.save()
class CustomerProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
university = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
role = models.CharField(max_length = 10, default = 'CUSTOMER')
needLaundryDone = models.BooleanField(default = False)
def __str__(self):
return self.user.username
@receiver(post_save, sender=User)
def create_customer_profile(sender, instance, created, **kwargs):
if created:
CustomerProfile.objects.create(user=instance)
@receiver(post_save, sender=User)
def save_customer_profile(sender, instance, **kwargs):
instance.customerprofile.save()
forms.py:
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
class WorkerSignUpForm(UserCreationForm):
#birth_date and university fields need to be declared seperately because they are not apart of User:
birth_date = forms.DateField(help_text='Required. Format: YYYY-MM-DD')
university = forms.CharField()
class Meta:
model = User
fields = ('username',
'email',
'first_name',
'last_name',
'birth_date',
'university',
'password1',
'password2',)
class CustomerSignUpForm(UserCreationForm):
#birth_date and university fields need to be declared seperately because they are not apart of User:
birth_date = forms.DateField(help_text='Required. Format: YYYY-MM-DD')
university = forms.CharField()
class Meta:
model = User
fields = ('username',
'email',
'first_name',
'last_name',
'birth_date',
'university',
'password1',
'password2',)
views.py:
def signup(request):
if request.method == 'POST':
form_worker = WorkerSignUpForm(request.POST)
form_customer = CustomerSignUpForm(request.POST)
if form_worker.is_valid():
user = form_worker.save()
user.refresh_from_db() # load the profile instance created by the signal
user.workerprofile.birth_date = form_worker.cleaned_data.get('birth_date')
user.workerprofile.university = form_worker.cleaned_data.get('university')
user.save() # explicitly save custom fields not in User model
raw_password = form_worker.cleaned_data.get('password1')
user = authenticate(username=user.username, password=raw_password)
login(request, user) # login user after signup
return redirect('home')
elif form_customer.is_valid():
user = form_customer.save()
user.refresh_from_db() # load the profile instance created by the signal
user.customerprofile.birth_date = form_customer.cleaned_data.get('birth_date')
user.customerprofile.university = form_customer.cleaned_data.get('university')
user.save() # explicitly save custom fields not in User model
raw_password = form_customer.cleaned_data.get('password1')
user = authenticate(username=user.username, password=raw_password)
login(request, user) # login user after signup
return redirect('home')
else:
form_worker = WorkerSignUpForm(request.POST)
form_customer = CustomerSignUpForm(request.POST)
return render(request, 'core/signup.html', {'form_worker': form_worker,'form_customer': form_customer })
signup.html:
{% extends 'core/base.html' %}
{% block head %}
<title> Sign Up</title>
{% endblock %}
{% block body %}
<h3>Sign Up As Worker</h3>
<form method="post">
{% csrf_token %}
{{ form_worker.as_p }}
<button type="submit">Sign up</button>
</form>
<h3>Sign Up As Customer</h3>
<form method="post">
{% csrf_token %}
{{ form_customer.as_p }}
<button type="submit">Sign up</button>
</form>
{% endblock %}
请勿在此处使用信号。它们都会在用户保存时触发,并且每个都创建相关的对象。
您应该删除这些信号,而是在视图中执行此操作。在每个表单的is_valid
块中,您只能创建所需的特定对象。
if form_worker.is_valid():
user = form_worker.save()
worker = WorkerProfile(user=user)
worker.birth_date = form_worker.cleaned_data.get('birth_date')
worker.university = form_worker.cleaned_data.get('university')
worker.save()
raw_password = form_worker.cleaned_data.get('password1')
...
elif form_customer.is_valid():
user = form_customer.save()
customer = CustomerProfile(user=user)
...
这是正常的:
user = models.OneToOneField(User, on_delete=models.CASCADE)
如果调用此两款车型,所以在保存过程中(),它会创建两个。
我建议你的是修改你的模型。你为什么不创建一个模型'Profil',并把一个布尔字段'is_customer'True/False?
我打算增加一些功能,比如如果你是一个客户,你按下一个按钮,它表示你正在寻找某人提供服务(诸如'lookingForService'之类的客户的布尔字段),然后必须添加诸如付款信息(向工人发送付款的地方以及从客户那里获得付款的地方)。如果客户/工作人员每个人的'个人资料'中的某些字段总是等于null或空字符串(即工作人员不需要'lookForService'字段),那么这样可以吗?工人? –
如果您将某个字段设置为Null或False,则这不是问题。我的意思是,基本上这在用户不填写他的个人资料字段的应用程序中并不罕见。 – GrandGTO
我同意丹尼尔,不要使用信号。 – GrandGTO
@DanielRoseman我已经更新了你所说的视图,它太长了评论,所以我把它放在这里https://jsfiddle.net/jkm74fv4/。但是现在,即使我以客户身份注册,所有内容都将作为“工作人员”配置文件存储起来? –
当您实例化表单以区分它们时,您需要使用前缀。虽然仔细观察,但我不明白为什么你有两种形式;为什么没有一个形式,与工人/客户复选框? –