Создано двойных пользователей - PullRequest
0 голосов
/ 05 мая 2020

У меня проблема с моим кодом в том смысле, что когда студент регистрируется, создается двойной экземпляр студента. Я не знаю, в чем проблема с этим блоком кода. Пожалуйста, помогите, также я не знаю, как установить связь между учителем и учеником, чтобы позволить учителю добавлять результаты для учеников.

views.py

from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from .forms import UserRegisterForm,UserUpdateForm ,InformationUpdateForm,InformationForm

def home(request):
    return render(request, 'student/home.html')

def register(request):
    if request.method == 'POST':
        form = UserRegisterForm(request.POST)
        a_form=InformationForm(request.POST)
        #  ####and a_form.is_valid()
        if form.is_valid() and a_form.is_valid():
            user = form.save()
            # form.save()
            #finally this get links the models, forms and views for user input and all information is registered
            information = a_form.save()
            # a_form.save()
            user.information.majors=a_form.cleaned_data.get('majors')
            user.information.department=a_form.cleaned_data.get('department')
            user.information.nationality=a_form.cleaned_data.get('nationality')
            user.information.date_of_birth=a_form.cleaned_data.get('date_of_birth')
            user.information.passport_number=a_form.cleaned_data.get('passport_number')
            user.information.phone_number=a_form.cleaned_data.get('phone_number')
            user.information.sex=a_form.cleaned_data.get('sex')
            user.save()
            information.save()
            # for this type user input is for for username,last,first and email is registered
            # form.save()

            username = form.cleaned_data.get('username')

            messages.success(request, f'Your account has been created! You are now able to log in')
            return redirect('login')
    else:
        form = UserRegisterForm()
        a_form = InformationForm()
    context={'form':form,'a_form':a_form }#,'a_form':a_form
    return render(request, 'student/register.html', context)


@login_required
def profile(request):
    return render(request, 'student/profile.html')#,context

@login_required
def profile_update(request):
    if request.method == 'POST':
        u_form=UserUpdateForm(request.POST,instance=request.user)
        i_form=InformationUpdateForm(request.POST,request.FILES,instance=request.user.information)
        if u_form.is_valid() and i_form.is_valid():
            u_form.save()
            i_form.save()
            messages.success(request, f'Your account has been updated!')
            return redirect('profile')
    else:
        u_form=UserUpdateForm(instance=request.user)
        i_form=InformationUpdateForm(instance=request.user.information)
    context={'u_form': u_form,
            'i_form':i_form}
    return render(request, 'student/profile_update.html',context)

models.py


from django.db import models
from django.contrib.auth.models import User
from PIL import Image

# CHOICES=[('M','Male'),
#          ('F','Female')]


class Information(models.Model):
    M='Male'
    F='Female'
    SELECT_GENDER_CHOICE=[(M, 'Male'),
        (F, 'Female')]
########################################################
    B='Bachelors'
    Ma='Masters'
    P='PhD'
    SELECT_DEGREE_CHOICE=[(B, 'Bachelors'),
        (Ma, 'Masters'),(P, 'PhD')]
#########################################################
    Y1='1 year'
    Y2='2 year'
    Y3='3 year'
    Y4='4 year'
    Y5='5 year'
    SELECT_YEARS_CHOICE=[(Y1, '1 year'),(Y2, '2 year'),(Y3, '3 year'),(Y4, '4 year'),(Y5, '5 year')]

    user = models.OneToOneField(User,null=True,on_delete=models.CASCADE)
    image = models.ImageField(default='default.jpg', upload_to='student')
    nationality=models.CharField(max_length=120,blank=False)
    sex=models.CharField(max_length=8,choices=SELECT_GENDER_CHOICE,default=M)
    department=models.CharField(max_length=120,blank=False)
    years=models.CharField(max_length=120,blank=False,choices=SELECT_YEARS_CHOICE,default=Y1,null=True)
    degree=models.CharField(max_length=120,blank=False,choices=SELECT_DEGREE_CHOICE,null=True)
    majors=models.CharField(max_length=500,blank=False)
    phone_number=models.CharField(max_length=12,blank=False)
    passport_number=models.CharField(max_length=50,blank=False)#unique=True)
    date_of_birth=models.CharField(max_length=10,blank=False)
 report=models.FileField(default='StudentResults/DEFAULT_SHEET.xlsx',upload_to='StudentResults',max_length=500,blank=True)#,null=True
    reg_no=models.CharField(max_length=10,null=True,unique=True)

    def __str__(self):
        return f'{self.passport_number} Information'


    def save(self,*args, **kwargs):
        super().save(*args, **kwargs)

        img=Image.open(self.image.path)

        if img.height>300 or img.width>300:
            output_size=(300,300)
            img.thumbnail(output_size)
            img.save(self.image.path)

forms.py


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



# CHOICES=[('M','Male'),
#          ('F','Female')]

class UserRegisterForm(UserCreationForm):
    email = forms.EmailField(widget=forms.TextInput(attrs={'placeholder': 'Email'}))
    username = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Username'}))
    first_name = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'First name'}))
    last_name = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Last name'}))
    password1 = forms.CharField(widget=forms.PasswordInput(attrs={'placeholder': 'Password'}))
    password2 = forms.CharField(widget=forms.PasswordInput(attrs={'placeholder': 'Confirm'}))


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

class InformationForm(forms.ModelForm):
    #sex=forms.ChoiceField(choices=CHOICES)
    department = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Department'}))
    majors = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Majors'}))
    nationality = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Nationality'}))
    date_of_birth = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Date of birth'}))
    passport_number = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Passport number'}))
    phone_number = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Phone number'}))


    class Meta:
        model=Information
        fields=['department','majors','degree','years','nationality','date_of_birth','passport_number','phone_number','sex']


class UserUpdateForm(forms.ModelForm):
    email = forms.EmailField()

    class Meta:
        model = User
        fields = ['email']
        # def email(self):
        #     email = self.cleaned_data.get("email")#this gets the default title but does not override the required field
        # #you can have multiple nested if else/elif statements. You can use this for email validation
        #     if not ".com" in email:
        #         raise forms.ValidationError("This is not a email")
        #     else:
        #         return email

class InformationUpdateForm(forms.ModelForm):
    class Meta:
        model=Information
        fields=['phone_number']

signal.py

from django.db.models.signals import post_save
from django.contrib.auth.models import User
from django.dispatch import receiver
from .models import Information

@receiver(post_save,sender=User)
def create_information(sender,instance,created,**kwargs):
    if created:
        Information.objects.create(user=instance)



@receiver(post_save,sender=User)
def save_information(sender,instance,**kwargs):
    instance.information.save()

страница профиля студента

{% extends "student/base.html" %}
{% load crispy_forms_tags %}
{% block content %}

    <div class="content-section">
      <div class="media">
        <img class="rounded-circle account-img" src="{{ user.information.image.url }}">
        <div class="media-body">
          <p class="text-secondary">Username: {{ user.username }}</p>
          <p class="text-secondary">First Name: {{ user.first_name }}</p>
          <p class="text-secondary">Last Name: {{ user.last_name }}</p>
          <p class="text-secondary">Email: {{ user.email }}</p>
          <p class="text-secondary">Passport Number: {{ user.information.passport_number }}</p>
          <p class="text-secondary">Date of Birth: {{ user.information.date_of_birth }}</p>
          <p class="text-secondary">Sex: {{ user.information.sex }}</p>
          <p class="text-secondary">Phone Number: {{ user.information.phone_number }}</p>
          <p class="text-secondary">Nationality: {{ user.information.nationality }}</p>
          <p class="text-secondary">Majors: {{ user.information.majors }}</p>
          <p class="text-secondary">Depatrment: {{ user.information.department }}</p>
          <p class="text-secondary">Results: {{ user.information.result }}</p>
          <p class="text-secondary">Years: {{ user.information.years }}</p>
          <p class="text-secondary">Degree: {{ user.information.degree }}</p>
         <a class="btn btn-outline-info" href="{{ user.information.report.url}}">Download your Report</a>
        </div>
      </div>
     {% comment %} <form method="POST">
            {% csrf_token %}
            <fieldset class="form-group" enctype="multipart/form-data">
                <legend class="border-bottom mb-4">Profile Info</legend>
                {{ i_form|crispy }}
                {{ u_form|crispy }}
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-info" type="submit">Update</button>
            </div>
        </form>
    </div> {% endcomment %}

{% endblock content %}

Ответы [ 2 ]

1 голос
/ 05 мая 2020

Это потому, что вы сохраняете a_form.save(), а затем снова сохраняете user.information.save(). Вам нужно изменить код следующим образом:

user = form.save()
information = a_form.save(commit=False)
information.user = user
information.save()
messages.success(request, 'Your account has been created! You are now able to log in')
return redirect('login')

Вы можете удалить остальную часть кода, относящуюся к user.information, а также удалить сигналы. Вам не нужны сигналы для создания экземпляра информации, потому что для этого у вас есть формы.

0 голосов
/ 05 мая 2020

Вы получаете двойной экземпляр пользователя из-за сигнала create_information.

user = form.save() в следующем коде сохранит экземпляр User.

def register(request):
if request.method == 'POST':
    form = UserRegisterForm(request.POST)
    a_form =InformationForm(request.POST)
    if form.is_valid() and a_form.is_valid():
        # form.save() creates a user, and triggers create_information signal
        user = form.save()
        information = a_form.save()

Теперь у вас есть сигнал create_information, который срабатывает после сохранения экземпляра User (этот сигнал является post_save синглом).

Ваш user = form.save() создаст пользователя и вызовет сигнал create_information.

@receiver(post_save,sender=User)
def create_information(sender,instance,created,**kwargs):
    if created:
        Information.objects.create(user=instance)

Это сохранит еще один экземпляр Information, а поскольку модель Information имеет OneToOne сопоставление с User, еще один экземпляр User также сохраняется.

Дополнительное примечание : у вас также сохранены три Information экземпляра. Один создан сигналом create_information, второй - сигналом save_information, а третий - методом a_form.save(). Это число может быть больше, если срабатывают сигналы cycli c, но вы не уверены в этом, поэтому вам придется проверить это самостоятельно.

Решение :

Во-первых, избавьтесь от всех синглов.

Во-вторых, добавьте User в Information экземпляр перед его сохранением.

def register(request):
if request.method == 'POST':
    form = UserRegisterForm(request.POST)
    a_form =InformationForm(request.POST)
    if form.is_valid() and a_form.is_valid():
        user = form.save()
        information = a_form.save(commit=False)
        information.user = user
        information.save()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...