Ошибка при сохранении формы профиля в django admin - PullRequest
0 голосов
/ 05 апреля 2020

Я действительно испугался, потому что проблема звучит тривиально, но я не гуглил ничего связанного с этим. Я нашел один очень симуляционный вопрос Django Админ Создать форму Inline OneToOne , но в моем случае я не могу удалить сигнал, это нарушит нормальный способ создания пользователя в моем приложении. У меня есть модель Пользователь и профиль, связанные отношения OneToOne (models.py):

from django.db import models
from django.contrib.auth.models import AbstractUser

from django.db.models.signals import post_save, pre_save
from django.dispatch import receiver
from .managers import UserManager

class User(AbstractUser):
    """auth/login-related fields"""
    username = None
    email = models.EmailField(unique=True)
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []
    objects = UserManager()

    def __str__(self):
        return self.email 

class Profile(models.Model):
    """profile fields"""
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    about = models.CharField(max_length=2000, blank=True)
    telegram = models.CharField(max_length=25, blank=True)
    def save(self, *args, **kwargs):
        print('save profile', args, kwargs) # from admin it run 2 times, second with empty args, kwargs so PROBLEM HERE!!!
        print('save profile complete')

"""receivers to add a Profile for newly created users"""
@receiver(post_save, sender=User) 
def create_user_profile(sender, instance, created, **kwargs):
    print('create_user_profile', created, instance.id)
    if created:
        try:
            p = Profile.objects.create(user = instance)
            print('succsecc!!!!', p, p.id) ## here profile object created and got id
        except Exception as e:
            print('create profile error', e) # never prints
    else:
        instance.profile.save()

""" @receiver(post_save, sender=User) 
def save_user_profile(sender, instance, **kwargs):
    print('save_user_profile')
    try:
        instance.profile.save()
    except Exception:
            print('save profile error', Exception)
 """

Эта модель хорошо работает с внешнего вида моего приложения, пользователи регистрируются и заполняют свои профили, все в порядке. Проблема возникает, когда я пытаюсь сделать пользователя из django admin. Затем я получаю django.db.utils.IntegrityError: UNIQUE constraint failed: authenticate_profile.user_id.

Мой файл admin.py выглядит так:

from django.contrib import admin
from django.contrib.auth.models import Group

from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserCreationForm, UserChangeForm, ReadOnlyPasswordHashField
from django import forms

from django.contrib.auth import get_user_model
from .models import Profile
from .forms import SignUpForm

User = get_user_model()

class UserInline(admin.StackedInline):
    model = Profile
    can_delete = True
    verbose_name = Profile

    def save_model(self, request, obj, form, change):
        print('save_model profile', request.POST, obj, form, change) ## never prints
        super().save_model(request, obj, form, change)    

class CustomUserAdmin(UserAdmin):
    add_form = SignUpForm
    form = UserChangeForm
    model = User
    list_display = ('email', 'first_name', 'last_name', 'is_staff', 'is_active',)
    list_filter = ('email', 'first_name', 'last_name', 'is_staff', 'is_active',)
    fieldsets = (
        (None, {'fields': ('email', 'first_name', 'last_name' 'password1', 'password2')}),
        ('Permissions', {'fields': ('is_staff', 'is_active')}),
    )
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('email', 'first_name', 'last_name', 'password1', 'password2', 'is_staff', 'is_active')}
        ),
    )
    search_fields = ('email',)
    ordering = ('email',)
    inlines = (UserInline, )

    def save_model(self, request, obj, form, change):
        print('save_model user', request.POST, obj, form, change)
        super().save_model(request, obj, form, change)



admin.site.register(User, CustomUserAdmin)

Код в сигнале post_save успешно запускается и создает профиль, после чего django пытается сохранить профиль из встроенной формы и завершается с ошибкой django.db.utils.IntegrityError: UNIQUE constraint failed authenticate_profile.user_id. Из журналов я вижу, что Profile.save (), когда я создаю пользователя из admin, вызывается дважды, второй раз без аргументов и kwargs. Но когда я переопределяю метод сохранения модели профиля, чтобы не запускать super().save() без аргументов, у меня не возникает ошибок, но я не могу сохранить профиль как от администратора, так и от внешнего интерфейса. Таким образом, проблема заключается в этом методе - КАК ПЕРЕДАТЬ ЭТО, ЧТОБЫ РАБОТАТЬ ОБА ОТ АДМИНА И НОРМАЛЬНОГО РАБОЧЕГО ПОТОКА ?. Заранее спасибо!

1 Ответ

0 голосов
/ 05 апреля 2020

Это было сложно ... Я думаю, что вы забыли цитаты вокруг verbose_name. должно быть

class UserInline(admin.StackedInline):
    model = Profile
    can_delete = True
    verbose_name = 'Profile'
...