Я делаю приложение для клиники. Я нахожусь в финансовом разделе своего приложения. Я хочу получать доход от встреч. Когда я приступил к тестированию этой конечной точки в почтальоне, я получил следующую ошибку: AttributeError: Got AttributeError при попытке получить значение для поля user в сериализаторе UserInfoSerializer.
Поле сериализатора может быть названо неправильно и не соответствует ни одному атрибуту или ключу экземпляра User.
Исходный текст исключения был следующим: Объект «Пользователь» не имеет атрибута «пользователь».
Я являюсь отправляю вам свои файлы, чтобы вы могли мне помочь, так как у меня была эта ошибка в течение нескольких дней, и я не мог ее решить.
userinfo/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})"
< /code>
my 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', usuario_info)
gastos_totales = obtener_balance_por_periodo('GASTO', 'total', usuario_info)
ingresos_mes = obtener_balance_por_periodo('INGRESO', 'mensual', usuario_info)
ingresos_cotizados_mes = obtener_balance_por_periodo('INGRESO_COTIZADO', 'mensual', usuario_info)
gastos_mes = obtener_balance_por_periodo('GASTO', 'mensual', usuario_info)
ingresos_trimestre = obtener_balance_por_periodo('INGRESO', 'trimestral', usuario_info)
ingresos_cotizados_trimestre = obtener_balance_por_periodo('INGRESO_COTIZADO', 'trimestral', usuario_info)
gastos_trimestre = obtener_balance_por_periodo('GASTO', 'trimestral', usuario_info)
ingresos_anio = obtener_balance_por_periodo('INGRESO', 'anual', usuario_info)
ingresos_cotizados_anio = obtener_balance_por_periodo('INGRESO_COTIZADO', 'anual', usuario_info)
gastos_anio = obtener_balance_por_periodo('GASTO', 'anual', usuario_info)
return Response({
'ingresos_totales': ingresos_totales,
'ingresos_cotizados_totales': ingresos_cotizados_totales,
'gastos_totales': gastos_totales,
'ingresos_mes': ingresos_mes,
'ingresos_cotizados_mes': ingresos_cotizados_mes,
'gastos_mes': gastos_mes,
'ingresos_trimestre': ingresos_trimestre,
'ingresos_cotizados_trimestre': ingresos_cotizados_trimestre,
'gastos_trimestre': gastos_trimestre,
'ingresos_anio': ingresos_anio,
'ingresos_cotizados_anio': ingresos_cotizados_anio,
'gastos_anio': gastos_anio,
})
< /code>
my serializers.py < /p>
from rest_framework import serializers
from django.db import models
from finanzas.models import Transaccion, ConfiguracionFinanzas
from citas.models import Citas
from userinfo.models import UserInfo
from patients.models import Patient
from django.contrib.auth.models import User
from rest_framework.exceptions import ValidationError
from datetime import datetime
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'first_name', 'last_name', 'user']
class UserInfoSerializer(serializers.ModelSerializer):
user = UserSerializer()
class Meta:
model = UserInfo
fields = ['user', 'address', 'dni', 'postal_code', 'city', 'country', 'segundo_apellido']
def get_user(self, obj):
# Asegúrate de que el objeto user esté presente y se pase correctamente
return UserSerializer(obj.user).data if obj.user else None
class PatientSerializers(serializers.ModelSerializer):
class Meta:
model = Patient
fields = ['nombre', 'primer_apellido', 'segundo_apellido', 'dni', 'address', 'city', 'code_postal', 'country']
class CitaSerializers(serializers.ModelSerializer):
patient = PatientSerializers()
user = UserInfoSerializer()
class Meta:
model = Citas
fields = ['patient', 'fecha', 'descripcion', 'precio', 'cotizada', 'user']
def validate_precio(self, value):
if value < 0:
raise ValidationError("El precio de la cita no puede ser negativo.")
return value
def validate(self, data):
if data.get('fecha') > datetime.now():
raise ValidationError("La fecha de la cita no puede ser en el futuro.")
return data
class ConfiguracionFinanzasSerializer(serializers.ModelSerializer):
class Meta:
model = ConfiguracionFinanzas
fields = ['id', 'precio_cita_base', 'ultima_actualizacion']
def validate_precio_cita_base(self, value):
if value < 0:
raise ValidationError("El precio base de la cita no puede ser negativo.")
return value
class TransaccionSerializer(serializers.ModelSerializer):
cita = CitaSerializers()
user = UserInfoSerializer()
class Meta:
model = Transaccion
fields = ['id', 'tipo', 'monto', 'descripcion', 'fecha', 'cita', 'user', 'url']
def validate_monto(self, value):
if value
Подробнее здесь: [url]https://stackoverflow.com/questions/79388272/attributeerror-with-user-in-django-application[/url]
Я делаю приложение для клиники. Я нахожусь в финансовом разделе своего приложения. Я хочу получать доход от встреч. Когда я приступил к тестированию этой конечной точки в почтальоне, я получил следующую ошибку: AttributeError: Got AttributeError при попытке получить значение для поля user в сериализаторе UserInfoSerializer. Поле сериализатора может быть названо неправильно и не соответствует ни одному атрибуту или ключу экземпляра User. Исходный текст исключения был следующим: Объект «Пользователь» не имеет атрибута «пользователь». Я являюсь отправляю вам свои файлы, чтобы вы могли мне помочь, так как у меня была эта ошибка в течение нескольких дней, и я не мог ее решить. userinfo/models.py [code]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}"` [/code] Мои finanzas/models.py: [code]from django.db import models from citas.models import Citas from userinfo.models import UserInfo
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})" < /code> my 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
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, )
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)
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]
return Response({ 'ingresos_totales': ingresos_totales, 'ingresos_cotizados_totales': ingresos_cotizados_totales, 'gastos_totales': gastos_totales, 'ingresos_mes': ingresos_mes, 'ingresos_cotizados_mes': ingresos_cotizados_mes, 'gastos_mes': gastos_mes, 'ingresos_trimestre': ingresos_trimestre, 'ingresos_cotizados_trimestre': ingresos_cotizados_trimestre, 'gastos_trimestre': gastos_trimestre, 'ingresos_anio': ingresos_anio, 'ingresos_cotizados_anio': ingresos_cotizados_anio, 'gastos_anio': gastos_anio, }) < /code> my serializers.py < /p> from rest_framework import serializers from django.db import models from finanzas.models import Transaccion, ConfiguracionFinanzas from citas.models import Citas from userinfo.models import UserInfo from patients.models import Patient from django.contrib.auth.models import User from rest_framework.exceptions import ValidationError from datetime import datetime
class UserSerializer(serializers.ModelSerializer):
class Meta: model = User fields = ['id', 'first_name', 'last_name', 'user']
class UserInfoSerializer(serializers.ModelSerializer): user = UserSerializer()
class Meta: model = UserInfo fields = ['user', 'address', 'dni', 'postal_code', 'city', 'country', 'segundo_apellido']
def get_user(self, obj): # Asegúrate de que el objeto user esté presente y se pase correctamente return UserSerializer(obj.user).data if obj.user else None
class PatientSerializers(serializers.ModelSerializer): class Meta: model = Patient fields = ['nombre', 'primer_apellido', 'segundo_apellido', 'dni', 'address', 'city', 'code_postal', 'country']
class CitaSerializers(serializers.ModelSerializer): patient = PatientSerializers() user = UserInfoSerializer()
class Meta: model = Citas fields = ['patient', 'fecha', 'descripcion', 'precio', 'cotizada', 'user']
def validate_precio(self, value): if value < 0: raise ValidationError("El precio de la cita no puede ser negativo.") return value
def validate(self, data): if data.get('fecha') > datetime.now(): raise ValidationError("La fecha de la cita no puede ser en el futuro.") return data
class ConfiguracionFinanzasSerializer(serializers.ModelSerializer): class Meta: model = ConfiguracionFinanzas fields = ['id', 'precio_cita_base', 'ultima_actualizacion']
def validate_precio_cita_base(self, value): if value < 0: raise ValidationError("El precio base de la cita no puede ser negativo.") return value
class TransaccionSerializer(serializers.ModelSerializer): cita = CitaSerializers() user = UserInfoSerializer()
class Meta: model = Transaccion fields = ['id', 'tipo', 'monto', 'descripcion', 'fecha', 'cita', 'user', 'url']