Relación uno a uno: vincular un modelo de usuario a un modelo de perfil personalizado en Django

La traducción del artículo se preparó en vísperas del inicio del curso "Desarrollador web en Python" .






Pfft ... ¿Bases de datos de nuevo?







Hay tres relaciones principales en una base de datos relacional:



  • Relación uno a uno;
  • Relación de uno a muchos;
  • Relación de muchos a muchos.


En este artículo, trataremos el primero de ellos, la relación uno a uno.



Por lo general, Django ya tiene un modelo de usuario que viene con el marco. Viene con sus propios campos, métodos, atributos, etc. La desventaja de este modelo de usuario es que no le permite agregar campos personalizados aparte de los valores predeterminados que ya se proporcionan en Django. Esto puede ser un problema serio ya que un desarrollador puede necesitar configurar completamente un perfil de usuario / cliente de un grupo de usuarios autenticados. Por ejemplo, un sitio de blog puede necesitar un perfil de autor, que incluirá la foto de un usuario, la dirección de contacto, el pasatiempo, el nicho, etc. Y el modelo de usuario que viene con Django no lo permite.



Para resolver este problema, los desarrolladores crean un modelo de perfil personalizado y lo conectan al modelo de usuario predeterminado en Django usando una relación uno a uno. Sucede que se garantiza que el usuario está conectado a un perfil y viceversa. Además, esta mecánica permite un mejor control sobre la personalización del modelo de perfil.



Ahora te mostraré cómo puedes hacer esto en Django.



1. Utilice el modelo de usuario predeterminado de Django.

En la aplicación donde desea crear un perfil, cree un nuevo archivo forms.py . En forms.py, importe los siguientes módulos:



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


Crea una clase para heredar UserCreationForm. Dentro de esta clase, cree otra metaclase que tendrá dos variables: modely fields. La variable modelcontendrá su modelo de usuario y la variable contendrá los fieldscampos de formulario que se crearán.



class createUserForm(UserCreationForm):
    class meta:
        model = User
        fields = ['username', 'password1', 'password2']


El código anterior creará un formulario con campos para nombre de usuario, contraseña y confirmación de contraseña.



2. Cree su modelo de perfil de usuario personalizado.



En su archivo models.py, importe el modelo de usuario predeterminado.



from django.contrib.auth.models import User


A continuación, debe crear su propio modelo de perfil y también crear un campo de usuario con una relación de uno a uno con el modelo de usuario predeterminado en Django.



class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, null=True,)
    name = models.CharField(max_length=200, null=True)
    email = models.CharField(max_length=200, null=True)
    address = models.CharField(max_length=200, null=True)

    def __str__(self):
        return self.name


3. Cree una forma para su modelo de perfil.



Abra el archivo form.py e importe su modelo de perfil desde models.py , también agregue algunas otras importaciones que serán útiles al crear su formulario de perfil.



from django import forms
from django.utils.translation import ugettext_lazy as _
from .models import Profile


Luego crea una clase que heredará de forms.ModelForm. En esta clase, cree otra metaclase que contenga dos variables: modely fields. La variable modelcontiene el modelo de perfil y fieldslos campos de formulario que se crearán.



class profileForm(forms.ModelForm):
    class Meta:
        model = Profile
        fields = ['name', 'email', 'address']
#The labels attribute is optional. It is used to define the labels of the form fields created   
        labels = {
                "name": _("Name     "),
                "email": _("Email Address"),
                "address": _("Street Address"),
                }


Ahora que los formularios están listos, definiremos la lógica para views.py antes de renderizarlo en nuestras plantillas.



4. Agregue la lógica a views.py .



Para trabajar con formularios creados en forms.py, debe importarlos a nuestro views.py y agregar algunos módulos más que serán útiles para crear lógica.



from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login,
from django.contrib import messages
from .models import Profile
from .forms import createUserForm, profileForm


Ahora creemos una página de registro. Vamos a llamarlo registerPage . Creemos un diccionario de contexto vacío y devolvamos el render.



def registerPage(request):    
    context = {}
    return render(request, 'app_name/register.html', context)


Asignemos valores del formulario a las variables llamando al método POST. Luego pasaremos las variables al diccionario de contexto.



def registerPage(request):
    if request.method == 'POST':
        form = createUserForm(request.POST)
        profile_form = profileForm(request.POST)

    context = {'form': form, 'profile_form': profile_form}
    return render(request, 'app_name/register.html', context)


Luego validaremos ambos formularios y los guardaremos posteriormente.



def registerPage(request):
    if request.method == 'POST':
        form = createUserForm(request.POST)
        profile_form = profileForm(request.POST)

        if form.is_valid() and profile_form.is_valid():
            user = form.save()

            #we don't save the profile_form here because we have to first get the value of profile_form, assign the user to the OneToOneField created in models before we now save the profile_form. 

            profile = profile_form.save(commit=False)
            profile.user = user

            profile.save()

    context = {'form': form, 'profile_form': profile_form}
    return render(request, 'app_name/register.html', context)


Si los valores del formulario se validan y guardan, mostraremos un mensaje de éxito y redirigiremos al usuario a la página de inicio de sesión.



def registerPage(request):
    if request.method == 'POST':
        form = createUserForm(request.POST)
        profile_form = profileForm(request.POST)

        if form.is_valid() and profile_form.is_valid():
            user = form.save()

            #we don't save the profile_form here because we have to first get the value of profile_form, assign the user to the OneToOneField created in models before we now save the profile_form. 

            profile = profile_form.save(commit=False)
            profile.user = user

            profile.save()

            messages.success(request,  'Your account has been successfully created')

            return redirect('login')

    context = {'form': form, 'profile_form': profile_form}
    return render(request, 'app_name/register.html', context)


5. Renderice la plantilla



En el archivo, register.htmlcree una etiqueta de formulario utilizando el método POST y actioncon un valor de cadena vacío. En la etiqueta de formulario colocaremos csrf_tokenen el formato de plantilla de django, y luego renderizaremos dinámicamente los formularios (formularios de usuario y perfil). Además, no olvidemos el botón de enviar.



<form method="POST" action="">
                {% csrf_token %}
                    <h3>Register Profile</h3>

                    <div class="form-field">
                        {{profile_form.name.label_tag}}
                        {{profile_form.name}}
                    </div>
                    <div class="form-field">
                        {{form.username.errors}}
                        {{form.username.label_tag}}
                        {{form.username}}
                    </div>
                    <div class="form-field">
                        {{profile_form.email.label_tag}}
                        {{profile_form.email}}
                    </div>
                    <div class="form-field">
                        {{profile_form.address.label_tag}}
                        {{profile_form.address}}
                    </div>
                    <div class="form-field">
                        {{form.password1.errors}}
                        {{form.password1.label_tag}}
                        {{form.password1}}
                    </div>
                    <div class="form-field">
                        {{form.password2.errors}}
                        {{form.password2.label_tag}}
                        {{form.password2}}
                    </div>

                <hr>
                <input id="form-button" class="btn btn-success btn-block" type="submit" value="Create Profile">
                <br>
                    {{form.non_field_errors}}
                <p>Already have an account? <a href="{% url 'login' %}">Login</a></p>
            </form>


Dado que después de completar el formulario, validarlo y guardarlo, nos redireccionamos a la página de inicio de sesión, se mostrará un mensaje sobre el éxito de la operación en la página de inicio de sesión en la parte inferior derecha antes de la inscripción “¿No tienes cuenta? Registrarse " .



 <form method="POST" action="">
                   ...
                 <hr>
                <input id="form-button" class="btn btn-success btn-block" type="submit" value="Login">
                
                {% for message in messages %}
                <p>{{message}}</p>
                {% endfor %}
                <p>Don't have an account? <a href="{% url 'store:register' %}">Register</a></p>
            </form>


Así es como crea un modelo de perfil para su sitio que está vinculado a su modelo de usuario en una relación uno a uno.








All Articles