简体   繁体   中英

How to link an existing model with user model in Django

This is a quite simple question I think, but I'm new with Django and searching the best/correct way to do things. So forgive me if I'm asking stupid questions.

I have a model called Person in my Django app. It contains just basic info of a person, no personal data involved yet:

class Person(models.Model):

    birthday = models.DateField(null=True)

    gender = models.CharField(max_length=10)

    height = models.CharField(max_length=3)

    weight = models.CharField(max_length=3)

Now I want to also add a feature for the person to register and log in. What is the correct way to do this? Many tutorials seem to suggest using the forms.py file, like this for example:

from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User

class RegisterForm(UserCreationForm):
    birthdate = forms.DateField()
    discord_id = forms.CharField(max_length=100, help_text='Discord ID')
    zoom_id = forms.CharField(max_length=100, help_text='Zoom ID')

    class Meta:
        model = User
        fields = ["username", "password1", "password2", "birthdate", "email", "discord_id", "zoom_id"]

How would I use/link my existing Person model with this built in User -model? Or do I need a separate model in Models.py at all? Do I just create the User-model like above in the forms.py and add my custom fields into it?

You can refer the django docs on extending user model:

https://docs.djangoproject.com/en/3.2/topics/auth/customizing/#extending-the-existing-user-model

There are two approaches. You can have a OneToOne relation with your model to django user model to add additional fields. Or you can extend the abstract user model from django to create a custom user.

from django.contrib.auth.models import AbstractUser

    class Person(AbstractUser):
        birthday = models.DateField(null=True)

        gender = models.CharField(max_length=10)

        height = models.CharField(max_length=3)

        weight = models.CharField(max_length=3)

Also you need to mark the custom user in settings:

AUTH_USER_MODEL = 'myapp.Person'

Then that model can be used in the form:

from django.contrib.auth.forms import UserCreationForm
from .models import Person

class RegisterForm(UserCreationForm):
    birthdate = forms.DateField()
    discord_id = forms.CharField(max_length=100, help_text='Discord ID')
    zoom_id = forms.CharField(max_length=100, help_text='Zoom ID')

    class Meta:
        model = Person
        fields = ["username", "password1", "password2", "birthdate", "email", "discord_id", "zoom_id"]

Alternatively you can do OneToOne relation:

from django.contrib.auth.models import User

class Person(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)

    birthday = models.DateField(null=True)

    gender = models.CharField(max_length=10)

    height = models.CharField(max_length=3)

    weight = models.CharField(max_length=3)

There are multiple ways to extend User model to add more custom fields based on your requirement to it.They are Proxy manager, OneToOneField, AbstractUser. My choice is to use one to one relationship field as it binds users to have only one profile.

from django.contrib.auth.models import User

class foo(models.Model):
   user = OneToOneField(User, on_delete=models.CASCADE)

In addition, you need to have django signals to bind extended foo model with User model. So that whatever changes made to foo, User can listen to it.

from django.db.models.signals import post_save
from django.dispatch import reciever

@reciever(sender=User, post_save)
def create_foo(sender, instance, created, **kwargs):
   if created:
      foo.objects.create(user=instance)

@reciever(sender=User, post_save)
def save_foo(sender, instance, **kwargs):
   instance.foo.save()

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