2017-08-17 115 views
1

我有一個網站,用戶應該能夠註冊爲「工人」或「客戶」,一個超級模型類型的網站。我創建了兩個模型WorkerProfileCustomerProfile以及這兩種表單,但是每次我提交客戶或工作者表單時,新用戶都會在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 %} 

回答

0

請勿在此處使用信號。它們都會在用戶保存時觸發,並且每個都創建相關的對象。

您應該刪除這些信號,而是在視圖中執行此操作。在每個表單的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) 
    ... 
+0

我同意丹尼爾,不要使用信號。 – GrandGTO

+0

@DanielRoseman我已經更新了你所說的視圖,它太長了評論,所以我把它放在這裏https://jsfiddle.net/jkm74fv4/。但是現在,即使我以客戶身份註冊,所有內容都將作爲「工作人員」配置文件存儲起來? –

+0

當您實例化表單以區分它們時,您需要使用前綴。雖然仔細觀察,但我不明白爲什麼你有兩種形式;爲什麼沒有一個形式,與工人/客戶複選框? –

0

這是正常的:

user = models.OneToOneField(User, on_delete=models.CASCADE) 

如果調用此兩款車型,所以在保存過程中(),它會創建兩個。

我建議你的是修改你的模型。你爲什麼不創建一個模型'Profil',並把一個布爾字段'is_customer'True/False?

+0

我打算增加一些功能,比如如果你是一個客戶,你按下一個按鈕,它表示你正在尋找某人提供服務(諸如'lookingForService'之類的客戶的布爾字段),然後必須添加諸如付款信息(向工人發送付款的地方以及從客戶那裏獲得付款的地方)。如果客戶/工作人員每個人的'個人資料'中的某些字段總是等於null或空字符串(即工作人員不需要'lookForService'字段),那麼這樣可以嗎?工人? –

+0

如果您將某個字段設置爲Null或False,則這不是問題。我的意思是,基本上這在用戶不填寫他的個人資料字段的應用程序中並不罕見。 – GrandGTO