Django诊所应用创建预约收入接口时出现AttributeError: 'User'对象无'user'属性的问题求助
Django诊所应用创建预约收入接口时出现AttributeError: 'User'对象无'user'属性的问题求助
大家好,我正在开发一款诊所APP的财务模块,想通过预约创建收入记录,但用Postman测试接口时遇到了如下错误:
AttributeError: Got AttributeError when attempting to get a value for field
useron serializerUserInfoSerializer.
The serializer field might be named incorrectly and not match any attribute or key on theUserinstance.
Original exception text was: 'User' object has no attribute 'user'.
这个问题已经卡了我好几天了,实在找不到解决办法,我把相关的代码文件贴出来,麻烦大家帮我看看问题出在哪!
userinfo/models.py
from django.db import models from django.contrib.auth.models import User class UserInfo(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="userInfo") address = models.CharField(max_length=255, blank=True, null=True) phone = models.CharField(max_length=15, blank=True, null=True) fecha_nacimiento = models.DateField(blank=True, null=True) dni = models.CharField(max_length=10, blank=True, null=True) postal_code = models.CharField(max_length=6, blank=True, null=True) city = models.CharField(max_length=200, blank=True, null=True) country = models.CharField(max_length=100, blank=True, null=True) segundo_apellido = models.CharField(max_length=200, blank=True) def __str__(self): return f"Información de {self.user.username}"
finanzas/models.py
from django.db import models from citas.models import Citas from userinfo.models import UserInfo class Transaccion(models.Model): INGRESO = 'INGRESO' GASTO = 'GASTO' INGRESO_COTIZADO = 'INGRESO_COTIZADO' TIPO_CHOICES = [ (INGRESO, 'Ingreso'), (GASTO, 'Gasto'), (INGRESO_COTIZADO, 'Ingreso_Cotizado') ] tipo = models.CharField( max_length=100, choices=TIPO_CHOICES, default=INGRESO, ) monto = models.DecimalField(max_digits=10, decimal_places=2) descripcion = models.TextField() fecha = models.DateTimeField(auto_now_add=True) cita = models.ForeignKey(Citas, on_delete=models.CASCADE) # Relacionado con la cita user = models.ForeignKey(UserInfo, on_delete=models.CASCADE) # Relacionado con el usuario que cotiza url = models.URLField(null=True, blank=True) def __str__(self): return f"Transacción de {self.tipo} por {self.monto} para la cita {self.cita}" class ConfiguracionFinanzas(models.Model): precio_cita_base = models.DecimalField(max_digits=10, decimal_places=2, default=0, verbose_name="Precio base de la cita") ultima_actualizacion = models.DateTimeField(auto_now=True) def __str__(self): return f"Configuración de Finanzas (Precio Cita: {self.precio_cita_base})"
views.py
# views.py from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from rest_framework.permissions import IsAuthenticated from finanzas.models import Transaccion, ConfiguracionFinanzas from citas.models import Citas from django.db.models import Sum from .serializers import TransaccionSerializer, ConfiguracionFinanzasSerializer from rest_framework.exceptions import NotFound from datetime import datetime, timedelta from django.utils import timezone def obtener_transacciones_por_periodo(filtro, usuario_info): hoy = timezone.now() transacciones = Transaccion.objects.filter(usuario=usuario_info) if filtro == 'mensual': inicio_mes = hoy.replace(day=1) transacciones = transacciones.filter(fecha__gte=inicio_mes) elif filtro == 'trimestral': inicio_trimestre = hoy - timedelta(days=90) transacciones = transacciones.filter(fecha__gte=inicio_trimestre) elif filtro == 'anual': inicio_anio = hoy.replace(month=1, day=1) transacciones = transacciones.filter(fecha__gte=inicio_anio) return transacciones def obtener_balance_por_periodo(tipo, filtro, usuario_info): hoy = timezone.now() transacciones = Transaccion.objects.filter(tipo=tipo, usuario=usuario_info) if filtro == 'mensual': inicio_mes = hoy.replace(day=1) transacciones = transacciones.filter(fecha__gte=inicio_mes) elif filtro == 'trimestral': inicio_trimestre = hoy - timedelta(days=90) transacciones = transacciones.filter(fecha__gte=inicio_trimestre) elif filtro == 'anual': inicio_anio = hoy.replace(month=1, day=1) transacciones = transacciones.filter(fecha__gte=inicio_anio) return transacciones.aggregate(Sum('monto'))['monto__sum'] or 0 class ListarGananciasCitasView(APIView): """ Listar las transacciones de ganancias por citas. """ def get(self, request): filtro = request.query_params.get('filtro', 'total') usuario_info = request.user.userInfo transacciones = obtener_transacciones_por_periodo(filtro, usuario_info) serializer = TransaccionSerializer(transacciones, many=True) return Response(serializer.data) class CrearGananciasCitasView(APIView): """ Vista para crear una transacción de tipo 'Ingreso' o 'Gasto'. Asocia la transacción a una cita y al usuario que la cotiza. """ def post(self, request, cita_id): if not request.user.is_authenticated: return Response({"detail": "Usuario no autenticado."}, status=status.HTTP_401_UNAUTHORIZED) try: cita = Citas.objects.get(id=cita_id) except Citas.DoesNotExist: raise NotFound("Cita no encontrada.") if cita.user != request.user: return Response({"detail": "No puedes modificar una cita de otro usuario."}, status=status.HTTP_403_FORBIDDEN) monto = request.data.get('monto') descripcion = request.data.get('descripcion') if monto is None or descripcion is None: return Response({"detail": "Se requieren los campos 'monto' y 'descripcion'."}, status=status.HTTP_400_BAD_REQUEST) tipo = 'INGRESO' if not cita.cotizada else 'INGRESO_COTIZADO' usuario_info = getattr(request.user, 'userInfo', None) if usuario_info is None: return Response({"detail": "Información del usuario no encontrada."}, status=status.HTTP_404_NOT_FOUND) transaccion = Transaccion.objects.create( tipo=tipo, monto=monto, descripcion=descripcion, cita=cita, user=usuario_info, ) serializer = TransaccionSerializer(transaccion) return Response(serializer.data, status=status.HTTP_201_CREATED) class MarcarCitaCotizadaView(APIView): """ Vista para marcar una cita como cotizada """ def post(self, request, cita_id): if not request.user.is_authenticated: return Response({"detail": "Usuario no autenticado."}, status=status.HTTP_401_UNAUTHORIZED) try: cita = Citas.objects.get(id=cita_id) except Citas.DoesNotExist: raise NotFound("Cita no encontrada.") if cita.usuario != request.user.userInfo: return Response({"detail": "No puedes modificar una cita de otro usuario."}, status=status.HTTP_403_FORBIDDEN) cita.cotizada = True cita.save() return Response({"message": "Cita marcada como cotizada"}, status=status.HTTP_200_OK) class CrearGastoView(APIView): """ Vista para crear un gasto independiente de las citas. """ def post(self, request): if not request.user.is_authenticated: return Response({"detail": "Usuario no autenticado."}, status=status.HTTP_401_UNAUTHORIZED) monto = request.data.get('monto') descripcion = request.data.get('descripcion') if monto is None or descripcion is None: return Response({"detail": "Se requieren los campos 'monto' y 'descripcion'."}, status=status.HTTP_400_BAD_REQUEST) tipo = "GASTO" url = request.data.get('url', None) usuario_info = request.user.userInfo gasto = Transaccion.objects.create( tipo=tipo, monto=monto, descripcion=descripcion, usuario=usuario_info, url=url ) serializer = TransaccionSerializer(gasto) return Response(serializer.data, status=status.HTTP_201_CREATED) class ListarGastosView(APIView): """ Listar los gastos del usuario autenticado """ def get(self, request): filtro = request.query_params.get('filtro', 'total') usuario_info = request.user.userInfo gastos = obtener_transacciones_por_periodo(filtro, usuario_info) serializer = TransaccionSerializer(gastos, many=True) return Response(serializer.data) class ConfiguracionFinanzasView(APIView): """ Obtener y actualizar la configuración de finanzas. """ def get(self, request): configuracion = ConfiguracionFinanzas.objects.first() if not configuracion: configuracion = ConfiguracionFinanzas.objects.create(precio_cita_base=0) serializer = ConfiguracionFinanzasSerializer(configuracion) return Response(serializer.data) def put(self, request): configuracion = ConfiguracionFinanzas.objects.first() if not configuracion: configuracion = ConfiguracionFinanzas.objects.create(precio_cita_base=0) serializer = ConfiguracionFinanzasSerializer(configuracion, data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) class FinanzasBalanceView(APIView): permission_classes = [IsAuthenticated] def get(self, request): usuario_info = request.user.userInfo # Obtención de los balances por periodo ingresos_totales = obtener_balance_por_periodo('INGRESO', 'total', usuario_info) ingresos_cotizados_totales = obtener_balance_por_periodo('INGRESO_COTIZADO', 'total', us
备注:内容来源于stack exchange,提问作者Rcacodedev
相关产品推荐
相关产品推荐

