django - 更新操作期间嵌套 AbstractUser 模型失败,“user_id 列中的空值违反非空约束”
问题描述
我正在创建嵌套抽象用户“来自用户的老师”,我的用例是“创建用户”->“然后让用户成为老师”
我能够创建用户并使用户成为教师,但我无法更新该字段,在以下情况下想要更新“teacher_cost”
模型.py
from django.contrib.postgres.fields import JSONField
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
uid = models.AutoField(verbose_name='ID',
serialize=False,
auto_created=True,
primary_key=True)
TEACHER = "Teacher"
STUDENT = "Student"
user_type = models.CharField(max_length=30, default=STUDENT)
contact_number = models.CharField(max_length=20, null=True, blank=True)
address = models.TextField(null=True, blank=True)
photo = models.ImageField(null=True, blank=True)
image = models.ImageField(upload_to='users/',
default='default/avatar.png')
approved = models.BooleanField(default=True)
def save(self, *args, **kwargs):
if self.user_type == User.TEACHER and self._state.adding:
self.approved = False
super().save(*args, **kwargs)
@property
def dishes(self):
ret = self.teacher.dish_set.all()
if ret:
return ret
else:
return ''
class Teacher(models.Model):
uid = models.AutoField(verbose_name='ID',
serialize=False,
auto_created=True,
primary_key=True)
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField(null=True, blank=True)
teacher_cost = models.DecimalField(
max_digits=5, decimal_places=2, null=True, blank=True)
languages = models.CharField(
max_length=50, null=True, blank=True)
address = models.TextField(null=True, blank=True)
def __str__(self):
return self.user.username
序列化程序.py
from rest_framework import serializers, exceptions
from django.contrib.auth.forms import PasswordResetForm
from django.conf import settings
from .models import *
from rest_auth import serializers as rest_auth_serializers
from django.utils.translation import ugettext_lazy as _
class UserDetailsSerializer(serializers.ModelSerializer):
"""
User model w/o password
"""
class Meta:
model = User
fields = ('pk', 'username', 'email',
'first_name', 'last_name', 'contact_number', 'user_type', 'photo', 'address')
read_only_fields = ('email', )
class UserTeacher(serializers.ModelSerializer):
class Meta:
model = User
fields = ('teacher',)
class TeacherDetails(serializers.ModelSerializer):
class Meta:
model = Teacher
fields = '__all__'
class TeacherFullDetails(serializers.ModelSerializer):
user_id = serializers.CharField(source='user.uid')
username = serializers.CharField(source='user.username')
first_name = serializers.CharField(source='user.first_name')
last_name = serializers.CharField(source='user.last_name')
photo = serializers.ImageField(
source='user.photo', max_length=None, use_url=True)
class Meta:
model = Teacher
fields = ('user_id', 'username', 'first_name', 'last_name', 'photo', 'teacher_cost')
class TeacherBriefDetails(serializers.ModelSerializer):
uid = serializers.CharField(source='user.uid')
first_name = serializers.CharField(source='user.first_name')
last_name = serializers.CharField(source='user.last_name')
class Meta:
model = Teacher
fields = ('uid', 'first_name', 'last_name',)
class TeacherProfileDetails(serializers.ModelSerializer):
contact_number = serializers.CharField(source='user.contact_number', required=False)
first_name = serializers.CharField(source='user.first_name', required=False)
last_name = serializers.CharField(source='user.last_name', required=False)
email = serializers.CharField(source='user.email', required=False)
photo = serializers.ImageField(
source='user.photo', max_length=None, use_url=True, required=False)
user = UserDetailsSerializer(read_only=True)
teacher_cost = serializers.CharField()
class Meta:
model = Teacher
fields = ('user', 'first_name', 'last_name', 'contact_number', 'email', 'photo',
'bio', 'teacher_cost')
class TeacherProfileSerializer(serializers.ModelSerializer):
user = UserDetailsSerializer()
class Meta:
model = Teacher
fields = ("bio", "teacher_cost", "user")
视图.py
from rest_framework import generics, viewsets, status, permissions
from .models import *
from .serializers import *
from rest_framework.response import Response
from django.db.models import Q
from .permissions import IsAuthenticatedAndOwner, IsTeacher
from django.shortcuts import get_object_or_404
from django.utils.datastructures import MultiValueDictKeyError
from rest_framework.views import APIView
import json
import logging
class TeacherProfile(viewsets.ModelViewSet):
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
lookup_field = "username"
def get_object(self):
if self.action == "partial_update":
return get_object_or_404(User, username=self.kwargs['username'])
return get_object_or_404(Teacher, user__username=self.kwargs['username'])
def get_serializer_class(self):
if self.action == "partial_update":
return UserDetailsSerializer
else:
return TeacherProfileDetails
class TeacherListCreateAPIView(APIView):
logger = logging.getLogger(__name__)
def get(self, request, *args, **kwargs):
teacherList = Teacher.objects.filter(user__username=kwargs["username"])
self.logger.info("Printing teacher list")
self.logger.info(teacherList)
serializers = TeacherProfileDetails(teacherList, many=True)
return Response(serializers.data)
def post(self, request, *args, **kwargs):
self.logger.info("-----------------put ------------")
serializers = TeacherProfileDetails(data=request.data)
# photo = request.FILES['file']
if serializers.is_valid():
serializers.save()
return Response(serializers.data, status=status.HTTP_201_CREATED)
return Response(serializers.errors, status=status.HTTP_400_BAD_REQUEST)
def put(self, request, *args, **kwargs):
serializers = TeacherProfileDetails(data=request.data, many=True)
self.logger.info(serializers)
if serializers.is_valid():
serializers.save()
return Response(serializers.data, status=status.HTTP_201_CREATED)
return Response(serializers.errors, status=status.HTTP_400_BAD_REQUEST)
# /user/<str:username>/profile
class UserProfile(viewsets.ModelViewSet):
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
lookup_field = "username"
def get_object(self):
return get_object_or_404(User, username=self.kwargs['username'])
def get_serializer_class(self):
return UserDetailsSerializer
网址.py
from django.urls import path
from .views import *
urlpatterns = [
path('teacher/<str:username>/profile',
TeacherProfile.as_view({'get': 'retrieve', 'delete': 'destroy', 'patch': 'partial_update'})),
path('teacherlist/<str:username>/',
TeacherListCreateAPIView.as_view(), name="teacher-list"),
]
调用 post 命令更新用户配置文件时出现以下错误
邮政
http://localhost:8002/api/v1/teacherlist/rayees/
表单json数据
{
"teacher_cost": "25.00"
}
低于错误
IntegrityError at /api/v1/teacherlist/rayees/
null value in column "user_id" violates not-null constraint
DETAIL: Failing row contains (2, null, 25.00, null, null, null).
Request Method: POST
Request URL: http://localhost:8002/api/v1/teacherlist/rayees/
Django Version: 2.2.4
解决方案
因为在模型中Teacher
用户是必填字段,并且您正在发送发布请求,它将使用该用户创建新老师。如果您想创建新老师,那么您应该使用帖子,因为您需要该用户
如果要更新用户的详细信息,可以使用 patch 方法,检查 put 方法代码
class TeacherListCreateAPIView(APIView):
logger = logging.getLogger(__name__)
def get(self, request, *args, **kwargs):
teacherList = Teacher.objects.filter(user__username=kwargs["username"])
self.logger.info("Printing teacher list")
self.logger.info(teacherList)
serializers = TeacherProfileDetails(teacherList, many=True)
return Response(serializers.data)
def post(self, request, *args, **kwargs):
""" creating new user """
serializers = TeacherProfileDetails(data=request.data)
# photo = request.FILES['file']
if serializers.is_valid():
serializer.validated_data['user'] = User.objects.filter(username=kwarsg['username'])
serializers.save()
return Response(serializers.data, status=status.HTTP_201_CREATED)
return Response(serializers.errors, status=status.HTTP_400_BAD_REQUEST)
def patch(self, request, *args, **kwargs):
teacher = TeacherProfileDetails.objects.get(user__username=kwargs['username'])
serializers = TeacherProfileDetails(data=request.data, instance=teacher)
self.logger.info(serializers)
if serializers.is_valid():
serializers.save()
return Response(serializers.data, status=status.HTTP_201_CREATED)
return Response(serializers.errors, status=status.HTTP_400_BAD_REQUEST)
现在您可以使用给定的数据发出补丁请求,http://localhost:8002/api/v1/teacherlist/rayees/
它将更新记录。
推荐阅读
- powershell - 如何在 Powershell Menu 中创建 Menu 洞察力
- excel - excel统计出现或延迟值
- c - 用 C 读写文件
- swift - IBOutlet 在 IBDesignable 类中为零
- c# - 调用服务失败。
- mysql - MySQL 8.0 'C:\Program Files\MySQL\MySQL Server 8.0\data\' (OS errno 2 - 没有这样的文件或目录) - 无法从 cmd 找到 db 的数据
- vba - 使用 VBA 获取 SharePoint 文档库记录
- c# - 保存 Outlook.MailItem 异步?
- mysql - 从布尔字段 = false 的数据库中选择
- java - 如何识别另一个图像中的图像?