tutorial modelos many example def consultas avanzadas __str__ python django django-forms

python - many - Forma del modelo django. Incluir campos de modelos relacionados



many to many django (5)

A mi entender, usted desea actualizar el campo de nombre de usuario de auth.User, que es OneToOne relación de OneToOne con Student , esto es lo que haría ...

class StudentForm (forms.ModelForm): username = forms.Charfield(label=_(''Username'')) class Meta: model = Student fields = (''personalInfo'',) def clean_username(self): # using clean method change the value # you can put your logic here to update auth.User username = self.cleaned_data(''username'') # get AUTH USER MODEL in_db = get_user_model()._default_manager.update_or_create(username=username)

espero que esto ayude :)

Tengo un modelo, llamado Estudiante, que tiene algunos campos, y una relación OneToOne con un usuario (django.contrib.auth.User).

class Student(models.Model): phone = models.CharField(max_length = 25 ) birthdate = models.DateField(null=True) gender = models.CharField(max_length=1,choices = GENDER_CHOICES) city = models.CharField(max_length = 50) personalInfo = models.TextField() user = models.OneToOneField(User,unique=True)

Entonces, tengo un ModelForm para ese modelo

class StudentForm (forms.ModelForm): class Meta: model = Student

Usando el atributo de campos en la clase Meta, logré mostrar solo algunos campos en una plantilla. Sin embargo, ¿puedo indicar qué campos de usuario mostrar?

Algo como:

fields =(''personalInfo'',''user.username'')

Actualmente no está mostrando nada. Funciona solo con StudentFields aunque

Gracias por adelantado.


Ambas respuestas son correctas: los formularios en línea hacen que esto sea fácil.

Sin embargo, tenga en cuenta que la línea solo puede ir en una dirección: desde el modelo que tiene la clave externa. Sin tener claves primarias en ambas (mala, ya que podría tener A -> B y luego B -> A2), no puede tener el formato en línea en el modelo related_to.

Por ejemplo, si tiene una clase de perfil de usuario y desea poder tener estos, cuando se muestre, el objeto de usuario relacionado se muestre como en línea, no tendrá suerte.

Puede tener campos personalizados en un ModelForm, y usar esto como una forma más flexible, pero tenga en cuenta que ya no es "automático" como un ModelForm estándar / en línea.


Si no desea cambiar el AUTH_USER_MODEL que tiene muchos efectos secundarios, puede usar la herencia de tablas múltiples y subclase del modelo de usuario en lugar de AbstractUser . Esto creará una tabla de Estudiante con un OneToOneField llamado user_ptr que apunta a la tabla de Usuario .

Aquí un ejemplo

from django.contrib.auth.models import User from django.db import models from django.utils.translation import gettext_lazy as _ class Student(User): phone = models.CharField(max_length=25) birthdate = models.DateField(null=True) city = models.CharField(max_length=50) personalInfo = models.TextField() class Meta: verbose_name = _(''student'') verbose_name_plural = _(''students'')

Ahora puedes definir tu ModelForm así

class StudentForm(forms.ModelForm): class Meta: model = Student fields = (''first_name'', ''last_name'', ''username'', ''personalInfo'', ''phone'', ''birthdate'', ''city'')

También puede ampliar los formularios de usuario de django incorporados como este

from django.contrib.auth.forms import UserChangeForm class StudentForm(UserChangeForm): class Meta: model = Student fields = (''first_name'', ''last_name'', ''username'', ''personalInfo'', ''phone'', ''birthdate'', ''city'')

Para usar su formulario en el administrador de django, agregue lo siguiente a admin.py:

from django.contrib import admin from .views import StudentForm from .models import Student class StudentAdmin(admin.ModelAdmin): form = StudentForm admin.site.register(Student, StudentAdmin)

Al subclasificar el modelo de Usuario , la creación de una instancia de Estudiante creará automáticamente una nueva instancia de usuario pero no al revés. Por lo tanto, una instancia de usuario puede existir sin estar asociada con una instancia de estudiante . Si desea asegurarse de que se crea una instancia de Estudiante para cada Usuario en el sistema, puede usar la siguiente señal:

from django.contrib.auth.models import User from django.db.models.signals import post_save from django.dispatch import receiver from .models import Student @receiver(post_save, sender=User) def create_student(sender, instance, created, **kwargs): if created: student = Student(user_ptr_id=instance.pk) student.__dict__.update(instance.__dict__) student.save()


Un método alternativo que podría considerar es crear un modelo de usuario personalizado extendiendo los modelos AbstractUser o AbstractBaseUser en lugar de usar un enlace uno a uno con un modelo de perfil (en este caso, el modelo de Estudiante). Esto crearía un único modelo de usuario extendido que puede usar para crear un único ModelForm.

Por ejemplo, una forma de hacerlo sería extender el modelo AbstractUser :

from django.contrib.auth.models import AbstractUser class Student(AbstractUser): phone = models.CharField(max_length = 25 ) birthdate = models.DateField(null=True) gender = models.CharField(max_length=1,choices = GENDER_CHOICES) city = models.CharField(max_length = 50) personalInfo = models.TextField() # user = models.OneToOneField(User,unique=True) <= no longer required

En el archivo settings.py, actualice AUTH_USER_MODEL

AUTH_USER_MODEL = ''appname.models.Student''

actualiza el modelo en tu administrador:

from django.contrib import admin from django.contrib.auth.admin import UserAdmin from .models import Student admin.site.register(Student, UserAdmin)

Luego, puede usar un único ModelForm que tenga tanto los campos adicionales que necesita como los campos en el modelo de usuario original. En forms.py

from .models import Student class StudentForm (forms.ModelForm): class Meta: model = Student fields = [''personalInfo'', ''username'']

Una forma más complicada sería extender el AbstractBaseUser, esto se describe detalladamente en los documentos .

Sin embargo, no estoy seguro de que crear un modelo de usuario personalizado de esta manera para tener un ModelForm único y conveniente tenga sentido para su caso de uso. Esta es una decisión de diseño que debe tomar ya que crear modelos de usuario personalizados puede ser un ejercicio difícil.


Una práctica común es utilizar 2 formas para lograr su objetivo.

  • Un formulario para el Modelo de User :

    class UserForm(forms.ModelForm): ... Do stuff if necessary ... class Meta: model = User fields = (''the_fields'', ''you_want'')

  • Un formulario para el modelo de Student :

    class StudentForm (forms.ModelForm): ... Do other stuff if necessary ... class Meta: model = Student fields = (''the_fields'', ''you_want'')

  • Use ambos formularios en su vista (ejemplo de uso):

    def register(request): if request.method == ''POST'': user_form = UserForm(request.POST) student_form = StudentForm(request.POST) if user_form.is_valid() and student_form.is_valid(): user_form.save() student_form.save()

  • Renderiza los formularios juntos en tu plantilla:

    <form action="." method="post"> {% csrf_token %} {{ user_form.as_p }} {{ student_form.as_p }} <input type="submit" value="Submit"> </form>

Otra opción sería que cambie la relación de OneToOne a ForeignKey (esto depende completamente de usted y solo lo menciono, no lo recomiendo) y use inline_formsets para lograr el resultado deseado.