Ошибка целостности после отправки переменных POST из ModelForm (расширенная модель пользователя в Django) - PullRequest
0 голосов
/ 01 апреля 2019

Я создаю страницу регистрации сотрудников, чтобы создать нового пользователя (где никто не вошел, т.е. анонимный пользователь).У меня есть модель профиля (добавление дополнительных полей, таких как отдел, псевдоним и т. Д.), Которая выходит из модели пользователя в Django.Я упомянул пользователя как отношение один к одному с профилем.

Когда регистрируется новый персонал, он должен указать свой «stafftypeid» («Должность») из таблицы ModelChoiceField, ссылающейся на таблицу Staff_Type.Таблица User не хранит «stafftypeid», поэтому я расширил UserCreationForm.

Моя проблема заключается в том, что я могу успешно передавать переменные POST через формы, и пользователь (auth_user) создаст новую запись.Я вижу нового пользователя на странице Django / admin.Однако Profile не сможет создать сопровождающую новую запись, и я получу сообщение об ошибке («IntegrityError at / register / (1048,« Column 'staffTypeID' не может быть пустым ")").Странно, у меня есть все переменные POST, но переменные, необходимые для полей в таблице профиля, не передаются.

Это проблема наследования?Новая запись профиля должна создаваться только при создании нового пользователя.

Я пытался следовать учебным пособиям и другому коду из учебного пособия Кори Шафера Django 8, Simpleisbetterthancomplex (https://simpleisbetterthancomplex.com/tutorial/2016/07/22/how-to-extend-django-user-model.html#onetoone) и переполнения стека).

Я также попытался переписать def form.save () , а затем разделить мои формы на две (изначально только одна), поскольку их легче обрабатывать в базе данных.сторона. Я был бы очень благодарен за совет здесь!

Администратор \ models.py: (Staff_Type)

from django.db import models
from decimal import Decimal

class Staff_Type(models.Model):
    stafftypeid = models.AutoField(db_column='staffTypeID', primary_key=True)  
    stafftypedesc = models.CharField(db_column='staffTypeDesc', max_length=150)

    class Meta:
        ordering = ['stafftypedesc']
        unique_together = ('stafftypedesc',)
        db_table = 'stafftype'

    def __str__(self):
        return self.stafftypedesc

Users \ models.py:

from django.db import models
from django.contrib.auth.models import User
from decimal import Decimal


class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    stafftypeid = models.ForeignKey('Administrator.Staff_Type', models.DO_NOTHING, db_column='staffTypeID')
    employeeid = models.CharField(max_length=20)
    alias = models.CharField(max_length=20)
    department = models.CharField(max_length=150)
    organization = models.CharField(max_length=150)
    fte = models.DecimalField(max_digits=4, decimal_places=1, default=Decimal(100.0))


    def __str__(self):
        return f'{self.user.username} Profile'

Users \ 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 Profile


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


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

Users \ register.html:

{% extends "Administrator/adminBase.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="col-md-8">
    <div class="content-section">
        <form method="POST">
            {% csrf_token %}
            <fieldset class="form-group">
                <legend class="border-bottom mb-4">Register New User </legend>
                {{ user_form|crispy }}
                {{ profile_form|crispy }}
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-info" type="submit">Sign Up</button>
            </div>
        </form>
    </div>
</div>
{% endblock content %}

Users \ forms.py:


from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from Administrator.models import Staff_Type
from .models import Profile

from .models import Profile
from django.utils.translation import ugettext_lazy as _


class UserRegisterForm(UserCreationForm):
    email = forms.EmailField(max_length=150, label = "Email")
    first_name = forms.CharField(max_length=150, label = "First Name")
    last_name = forms.CharField(max_length=150, label = "Surname")

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


class ProfileForm(forms.ModelForm):
    stafftypeid = forms.ModelChoiceField(queryset=Staff_Type.objects.all(), empty_label="Staff Type")
    employeeid = forms.CharField(max_length=20, label="Employee ID")
    alias = forms.CharField(max_length=20, label="Alias")
    department = forms.CharField(max_length=150, label="Department")
    organization = forms.CharField(max_length=150, label="Organization")
    fte = forms.DecimalField(max_digits=4, decimal_places=1, min_value=0.0, max_value=100.0, label="FTE(%)")

    class Meta:
        model = Profile
        fields = ['stafftypeid', 'employeeid', 'alias', 'department', 'organization', 'fte']


Users \ views.py:

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


def register(request):
    if request.method == "POST":
        user_form = UserRegisterForm(request.POST)
        profile_form = ProfileForm(request.POST)
        if user_form.is_valid() and profile_form.is_valid():
            user_form.save()
            profile_form.save()
            username = user_form.cleaned_data.get('username')
            stafftypeid = profile_form.cleaned_data.get('stafftypeid')
            messages.success(request, f'Account created for {username}, with alias: {stafftypeid}')
            return redirect('admin-home')
    else:
        user_form = UserRegisterForm()
        profile_form = ProfileForm()
    return render(request, 'users/register.html', {'user_form': user_form, 'profile_form': profile_form})

Users \ apps.py:

from django.apps import AppConfig


class UsersConfig(AppConfig):
    name = 'users'

    def ready(self):
        import users.signals

1 Ответ

0 голосов
/ 02 апреля 2019

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

Вам не нужен этот сигнал. Вы создаете профиль в отдельной форме профиля и сохраняете его в виде. Вы должны удалить оба этих сигнала.

Затем обновите представление:

    if user_form.is_valid() and profile_form.is_valid():
        user = user_form.save()
        profile = profile_form.save(commit=False)
        profile.user = user
        profile.save()

(Отдельно, пожалуйста, прекратите называть ваши ForeignKeys как заканчивающиеся на "_id"; это не идентификаторы, это фактические связанные объекты.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...