Я пытаюсь использовать конечную точку API Django Ninja (с ModelSchema Django Ninja), чтобы обновить поле предпочтений часового пояса (tz_preference*) в модели пользователя моего приложения Django.
*Примечание. Поле tz_preference имеет значение по умолчанию и ограничено списком вариантов.
Когда я проверяю конечную точку API с помощью /api/docs, ответ продолжает возвращать значение по умолчанию поля tz_preference («Америка/Денвер»), хотя я даю ему другие допустимые значения в теле запроса («Тихоокеанский регион/Гонолулу», «Америка/Чикаго»). , и т. д.).
Я знаю, что мое поле tz_preference имеет значение по умолчанию «Америка/Денвер», поэтому, скорее всего, именно поэтому тело ответа имеет значение {"tz_preference": "America/Denver"}, но я не уверен, почему оно придерживается значения по умолчанию, а не использует значение, которое я ему указываю. тело запроса.
from django.db import models
from django.contrib.auth.models import PermissionsMixin
from django.contrib.auth.validators import ASCIIUsernameValidator
from django.utils.translation import gettext_lazy as _
from timezone_field import TimeZoneField
from zoneinfo import ZoneInfo
TZ_CHOICES = [
(ZoneInfo('Pacific/Honolulu'), 'Pacific/Honolulu'),
(ZoneInfo('America/Anchorage'), 'America/Anchorage'),
(ZoneInfo('America/Los_Angeles'), 'America/Los_Angeles'),
(ZoneInfo('US/Arizona'), 'US/Arizona'),
(ZoneInfo('America/Denver'), 'America/Denver'),
(ZoneInfo('America/Chicago'), 'America/Chicago'),
(ZoneInfo('America/New_York'), 'America/New_York'),
]
class CustomUser(AbstractBaseUser, PermissionsMixin):
username_validator = ASCIIUsernameValidator()
username = models.CharField(
_("username"),
max_length=150,
unique=True,
db_index=True,
validators=[username_validator],
error_messages = {
"unique": _("A user with that username already exists."),
},
)
email = models.EmailField(
_("email address"),
unique=True,
db_index=True,
help_text=_(
"Required."
),
error_messages = {
"unique": _("A user with that email address already exists."),
},
)
is_staff = models.BooleanField(_("staff status"), default=False,)
is_active = models.BooleanField(_("active"), default=True,)
""" -----------------FIELD I'M TRYING TO CHANGE------------------- """
tz_preference = TimeZoneField(
use_pytz=False,
choices=TZ_CHOICES,
default = "America/Denver",
choices_display = "STANDARD",
)
""" -------------------------------------------------------------- """
class CAT_CHOICES(models.TextChoices):
S = 'STUDENT', _('Student')
I = 'INSTRUCTOR', _('Instructor')
category = models.CharField(max_length=10, choices=CAT_CHOICES.choices)
objects = TerpUserManager()
EMAIL_FIELD = "email"
USERNAME_FIELD = "username"
REQUIRED_FIELDS = ["email", "category"]
Извините, если я включил слишком много кода для своей пользовательской модели. Поскольку мне интересно, вызывают ли обязательные поля неожиданное поведение, я оставил их.
# do ye django ninja stuff
from ninja import NinjaAPI
api = NinjaAPI()
# django models stuff (to get my custom user model)
from django.contrib.auth import get_user_model
User = get_user_model()
# ninja schema stuff
from ninja import Schema, ModelSchema
"""------------------------ SCHEMAS ------------------------------"""
class UserTimezoneSchema(ModelSchema):
class Meta:
model = User
fields = ['tz_preference']
class NotFoundSchema(Schema):
message: str
"""----------------------- ENDPOINTS -----------------------------"""
@api.put("/member/{member_id}", response = {200: UserTimezoneSchema, 404: NotFoundSchema})
def change_tz(request, member_id: int, data: UserTimezoneSchema):
try:
member = User.objects.get(pk=member_id)
member.tz_preference = data.tz_preference
member.save()
except User.DoesNotExist as e:
return 404, {'message': 'User does not exist'}
PUT /api/member/{member_id}){"tz_preference": "Pacific/Honolulu"}curl -X 'PUT' \
'http://127.0.0.1:8000/api/member/1' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"tz_preference": "Pacific/Honolulu"
}'
{
"tz_preference": "America/Denver"
}
content-length: 35
content-type: application/json; charset=utf-8
cross-origin-opener-policy: same-origin
date: Mon,01 Jul 2024 18:02:59 GMT
referrer-policy: same-origin
server: WSGIServer/0.2 CPython/3.10.14
x-content-type-options: nosniff
x-frame-options: DENY
Изображение схем ответа для этой конечной точки, которое я включил выше, из документации API, которую автоматически генерирует Django Ninja, подсказывает мне, что значение по умолчанию устанавливается автоматически независимо от тела запроса, но у меня нет опыта интерпретации. это автоматически сгенерированная документация, поэтому я не уверен.
И если проблема связана со значением этого поля по умолчанию в моей модели, я понятия не имею, как это решить.
ZoneInfo (я сомневаюсь, что это так, потому что простые текстовые данные — единственный тип данных, которые действительно могут быть отправлены через API, верно?)PATCH вместо PUT.




Оказывается, мне просто нужен был оператор возврата в функции, которую я написал для обработки запроса PUT:
@api.put("/member/{member_id}", response = {200: UserTimezoneSchema, 404: NotFoundSchema})
def change_tz(request, member_id: int, data: UserTimezoneSchema):
try:
member = User.objects.get(pk=member_id)
member.tz_preference = data.tz_preference
member.save()
return member
except User.DoesNotExist as e:
return 404, {'message': 'User does not exist'}
Спасибо @vitalik, создателю django-ninja, за указание мне на это.