简体   繁体   中英

How do i add custom fields to UserManager in Django

I am trying to create a user profile, i followed through a tutorial which has registration for only username, email and password but i want to be able to add other custom fields.

What i did:

Models.py:

class UserManager(BaseUserManager):
    def create_user(self, username, email, password=None,):
        if username is None:
            raise TypeError('User should have a userame')
        if email is None:
            raise TypeError('Users should have a Email')
        
        user = self.model(username=username , email = self.normalize_email(email))
        user.set_password(password)
        user.save()
        return user
    
    def create_superuser(self, username, email, password=None):
        if password is None:
            raise TypeError('User should have a password')
       
        user=self.create_user(username,email,password)
        user.is_superuser = True
        user.is_staff = True
        user.save()
        return user

class User(models.Model):
    dso = models.ForeignKey(Dso,related_name='dso',default=NULL,blank=False,on_delete=models.CASCADE)
    name = models.CharField(max_length=70, blank=False, default='')
    email = models.EmailField(max_length=70, blank=False, default='')
    password = models.CharField(max_length=70, blank=False, default='')
    address = models.CharField(max_length=70, blank=False, default='')
    roleId = models.IntegerField(blank=False, default='1')
    isActive = models.BooleanField(blank=False, default=True)
    customerId = models.CharField(max_length=70, blank=False, default='')
    
    dateJoined = models.DateTimeField(auto_now_add=False, blank=False, default=NULL)

    @property
    def energy_data(self):
        energydata = EnergyData.objects.filter(customerId=self.customerId).first()
        return energydata

Serializers.py:

class RegisterSerializer(serializers.ModelSerializer):
    password = serializers.CharField(max_length = 68, min_length=6, write_only = True)
    
    class Meta:
        model=User
        fields=['email','username','password','name','address','customerId', 
                  'dso', 'roleId']
    
    def validate(self, attrs):
        email = attrs.get('email', '')
        username = attrs.get('username', '')

        if not len(username) >= 4:
            raise serializers.ValidationError('Username must be morethan 4 letters or characters')
        return attrs

    def create(self, validated_data):
        return User.objects.create_user(**validated_data)

Views.py:

class RegisterView(generics.GenericAPIView):

    serializer_class= RegisterSerializer 
    def post(self, request):
        user = request.data
        serializer = self.serializer_class(data=user)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        user_data = serializer.data

        user= User.objects.get(email=user_data['email'])

        token = RefreshToken.for_user(user).access_token

        current_site = get_current_site(request).domain

        relativeLink = reverse('email-verify')
        
        absolute_url = 'http://'+current_site+relativeLink+"?token="+str(token)

        email_body= 'Hi '+ user.username + ' Use this link below to verify your email \n'+ absolute_url

        data = {'email_subject': 'Verify Your Email', 'email_body': email_body , 'to_email': user.email}

        Util.send_email(data)

        return Response(user_data, status = status.HTTP_201_CREATED)

URL Path:

path('register/', RegisterView.as_view(), name="register" )

When i do this and try to test i get the error, ' UserManager.create_user() got an unexpected keyword argument 'name' '

Please kindly help as i am new to django rest frameworrk.

In your serializers.py you have the fields list that includes the variable 'name', but it is never defined in the models.py

Try to change serializers.py

 fields=['email','username','password','address','customerId', 
                  'dso', 'roleId']

And modify the variable name in models.py to be username instead of name

 username = models.CharField(max_length=70, blank=False, default='') 

Based on my experience with Django having a Model called "user" is going to create problems at some point since Django already have a User model pre-installed in the backend.

I know this is not the exact answer you were looking for, this will probably spare you a headache in the future.

To create a user profile I created the following model linking the User model with a OneToOneField.

class Profile(models.Model):
    user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
    bio = models.TextField()
    profile_pic = models.ImageField(null=True, blank=True,upload_to="images/")
    

    def __str__(self):
        return str(self.user)

and obvioulsy imported

from django.contrib.auth.models import User

As a result,

  1. I would remove your User model

  2. Import "from django.contrib.auth.models import User"

  3. add to the first line of your UserManager Model, I would add

    "user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM