как выполнить post-запрос для вложенных serailizers в django rest framework

#python #django #django-rest-framework

#python #django #django-rest-framework

Вопрос:

Hii Я новичок в django rest Framework, я могу выполнять операции put delete и get, но не могу выполнять операции post
models.py

 class User(auth.models.User, auth.models.PermissionsMixin):
def __str__(self):
    return "@{}".format(self.username)
class User_log(models.Model):
    user = models.OneToOneField(auth.models.User,on_delete=models.CASCADE,related_name='user_logs')
    fullname=models.CharField(max_length=255)
    fb_login=models.BooleanField(default=False)
    def __str__(self):
        return self.fullname
 

serializers.py

 class userSerializers(serializers.ModelSerializer):
    password1=serializers.CharField(source="user.password1",write_only=True)
    password2=serializers.CharField(source="user.password2",write_only=True)
    fullname=serializers.CharField(source='user_logs.fullname')
    fb=serializers.BooleanField(source='user_logs.fb_login')
    class Meta:
        model = User
        fields=('id','username','email','password1','password2','fullname','fb')
        related_fields = ['user_logs']
    def update(self, instance, validated_data):
    # Handle related objects
        for related_obj_name in self.Meta.related_fields:
            data = validated_data.pop(related_obj_name)
            related_instance = getattr(instance, related_obj_name)

            # Same as default update implementation
            for attr_name, value in data.items():
                setattr(related_instance, attr_name, value)
            related_instance.save()
        return super(userSerializers,self).update(instance, validated_data)
 

urls.py

 from django.urls import path,include
from django.contrib.auth import views as auth_views
from . import views
from rest_framework import routers
router=routers.DefaultRouter()
router.register('accounts',views.Userview,basename='user')
app_name = 'accounts'

urlpatterns = [
    path('login/', auth_views.LoginView.as_view(template_name="accounts/login.html"),name='login'),
    path('logout/', auth_views.LogoutView.as_view(), name="logout"),
    path('signup/', views.SignUp.as_view(), name="signup"),
    path('password-reset/',
         auth_views.PasswordResetView.as_view(
             template_name='accounts/password_reset_email.html'
         ),
         name='password_reset'),
    path('password-reset/done/',
         auth_views.PasswordResetDoneView.as_view(
             template_name='accounts/password_reset_done.html'
         ),
         name='password_reset_done'),
    path('password-reset-confirm/<uidb64>/<token>/',
         auth_views.PasswordResetConfirmView.as_view(
             template_name='accounts/password_reset_confirm.html'
         ),
         name='password_reset_confirm'),
    path('password-reset-complete/',
         auth_views.PasswordResetCompleteView.as_view(
             template_name='accounts/password_reset_complete.html'
         ),
         name='password_reset_complete'),
    path('',include(router.urls)),
]
 

views.py

 class Userview(viewsets.ModelViewSet):
def get_serializer_class(self):
    return userSerializers
def get_queryset(self):
    return User.objects.all()
def list(self,request):
    queryset = User.objects.all()
    serializer=userSerializers(queryset,many=True)
    if serializer.is_valid:
        return Response(serializer.data)
 

это формат json, когда я выполняю запрос get

 [
{
    "id": 1,
    "username": "karm",
    "email": "karm@gmail.com",
    "fullname": "ss",
    "fb": false
}
]
 

Как упоминалось ранее, всякий раз, когда я выполняю put delete или получаю его работу, но это не относится к post, ошибка, которую я получаю, заключается в следующем:

 AssertionError at /accounts/accounts/
 

По .create() умолчанию метод не поддерживает доступные для записи поля с точечным исходным кодом.
Напишите явный .create() метод для сериализатора accounts.serializers.userSerializers или задайте read_only=True для полей сериализатора с пунктирным исходным кодом.

Ответ №1:

Здесь следует учитывать два момента:

  1. Сериализаторы DRF не поддерживают write_only . Вместо этого используйте extra_kwargs в блоке сериализатора Meta .
  2. Напишите create метод в своем сериализаторе. Примерный пример ниже.

Смотрите Это из документации для получения дополнительной информации о полях, доступных только для записи, в сериализаторах DRF.

 class userSerializers(serializers.ModelSerializer):
    password1=serializers.CharField(source="user.password1")
    password2=serializers.CharField(source="user.password2")
    fullname=serializers.CharField(source='user_logs.fullname')
    fb=serializers.BooleanField(source='user_logs.fb_login')
    class Meta:
        model = User
        fields
        fields=['id','username','email','password1','password2','fullname','fb']
        related_fields = ['user_logs']
        extra_kwargs = {
          'password1': {'write_only': True},
          'password2': {'write_only': True},
        }

    def create(self, validated_data): // adjust to fit your actual User model
        user = User(
            email=validated_data['email'],
            username=validated_data['username']
        )
        user.set_password(validated_data['password'])
        user.save()
        return user
 

Комментарии:

1. Его рабочее спасибо за это, просто еще одно одолжение, я хочу сделать пароль 1 и 2 поля только для записи, только когда запрос Post, если он УСТАНОВЛЕН, writeonly будет false

2. Создайте новый сериализатор с именем UpdateUserSerializer с нужными разрешениями. На ваш взгляд, переопределите поведение исправления по умолчанию, написав новый метод обновления в представлении, который использует UpdateUserSerializer. См. Документы DRF для получения дополнительной информации о переопределении поведения ModelViewSet по умолчанию.

Ответ №2:

Вы должны написать метод create, как вы делаете с помощью метода update. Попробуйте этот код в вашем serializer.py досье.

 def create(self, validated_data):
    profile_data = validated_data.pop('profile')
    user = User.objects.create(**validated_data)
    UserProfile.objects.create(user=user, **profile_data)
    return user
 

Надеюсь, это сработает для вас.

Комментарии:

1. даже это работает, спасибо за это, еще одно одолжение, я хочу сделать пароль 1 и 2 поля только для записи, только когда запрос Post, если он УСТАНОВЛЕН, writeonly будет false