Search code examples
pythondjangodjango-rest-frameworkdjango-serializer

How to fix error in Django serializers.py fields


enter image description hereI'm trying to send a post request from django app using rest framework but I keep having the following output:

{
    "user_name": [
        "This field is required."
    ],
    "email": [
        "This field is required."
    ],
    "company": [
        "This field is required."
    ],
    "state": [
        "This field is required."
    ],
    "city": [
        "This field is required."
    ],
    "address": [
        "This field is required."
    ],
    "phone_number": [
        "This field is required."
    ],
    "password": [
        "This field is required."
    ],
    "password_2": [
        "This field is required."
    ]
}

I have the following blocks of code:

urls.py

urlpatterns = [
     path("register_user/", account_register, name="register")

]

models.py

from django.contrib.auth.models import (AbstractBaseUser, BaseUserManager,
                                        PermissionsMixin)

from django.db import models
from django.utils.translation import gettext_lazy as _
from django_countries.fields import CountryField
from django.core.mail import send_mail 

class CustomManager(BaseUserManager):

    def create_superuser(self, email, user_name, password, **other_fields):

        other_fields.setdefault('is_staff', True)
        other_fields.setdefault('is_superuser', True)
        other_fields.setdefault('is_active', True)

        if other_fields.get('is_staff') is not True:
            raise ValueError(
                'Superuser must be assigned to is_staff=True.')
        if other_fields.get('is_superuser') is not True:
            raise ValueError(
                'Superuser must be assigned to is_superuser=True.')

        return self.create_user(email, user_name, password, **other_fields)

    def create_user(self, email, user_name, password, **other_fields):

        if not email:
            raise ValueError(_('You must provide an email address'))

        email = self.normalize_email(email)
        user = self.model(email=email, user_name=user_name,
                          **other_fields)
        user.set_password(password)
        user.save()
        return user

class UserBase(AbstractBaseUser, PermissionsMixin):
    user_name = models.CharField(max_length=30, unique=True)
    first_name = models.CharField(max_length=50, null=True, blank=True)
    last_name = models.CharField(max_length=50, null=True, blank=True)
    email = models.EmailField(max_length=254, unique=True)
    company = models.CharField(max_length=50)
    license_number = models.CharField(max_length=50)
    country = CountryField(null=True, blank=True)
    state = models.CharField(max_length=50)
    city = models.CharField(max_length=50)
    address = models.CharField(max_length=255)
    postcode = models.CharField(max_length=50, null=True, blank=True)
    phone_number = models.CharField(max_length=50, unique=True)
    #User status
    is_active = models.BooleanField(default=False)
    is_staff = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at= models.DateTimeField(auto_now=True)
    objects = CustomManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['user_name']
    
    class Meta:
        verbose_name: 'Accounts'
        verbose_name_plural = 'Accounts'
        
    def email_user(self, subject, message):
        send_mail(
            subject,
            message,
            '[email protected]',
            [self.email],
            fail_silently=False,
        )

    def __str__(self):
        return self.user_name

serializers.py

from rest_framework import serializers 
from rest_framework.serializers import ModelSerializer
from .models import UserBase


class registeration_serializer(serializers.ModelSerializer):
    password_2 = serializers.CharField(style={"input_type": "password"}, write_only=True)
    class Meta:
        model = UserBase
        fields = ['user_name', 'email',  'first_name', 'first_name', 'company', 
            'state', 'city', 'address', 'postcode', 'phone_number', 'password', 'password_2']
        extra_kwargs = {"password":{"write_only": True}}

    def save(self):
        account = UserBase(
            user_name = self.validated_data["user_name"],
            email = self.validated_data["email"],
            company = self.validated_data["company"],
            state = self.validated_data["state"],
            city = self.validated_data["city"],
            address = self.validated_data["address"],
            postcode = self.validated_data["postcode"],
            phone_number = self.validated_data["phone_number"],
            
        )
        password = self.validated_data["password"]
        password_2 = self.validated_data["password"]

        if password != password_2:
            raise serializers.ValidationError({"password":"Passwords do not match"})
        account.set_password(password)
        account.save()
        return account

views.py

@api_view(["POST",])
def account_register(request):
    if request.method == 'POST':
        register_serializer = registeration_serializer(data=request.data)
        data = {}
        if register_serializer.is_valid():
            account = register_serializer.save()
            data["response"] = "Welcome! Your account has been successfully created."
            data["email"] = account.email
        
        else:
            data = register_serializer.errors
        return Response (data)

I haven't seen any error with code. I have search online but haven't seen any solution that works for me. How do I get over this?


Solution

  • You need to post some of the data you're testing with, but generally as the response says, it seems that you're not providing these mandatory fields in the post body.

    To mark any field not required, you can simply add it explicitly in the serializer, for example:

    class MySerializer(serializer.ModelSerializer):
        usern_name= serializers.CharField(required=False)
    

    The required=False makes it not mandatory, also there is allow_null and others that you can find here