Как отобразить поля других моделей в представлении создания в Django?

Я пытаюсь создать несколько записей в базе данных. Я не могу ничего ввести для моделей Address. Я хотел бы иметь возможность добавлять отдельные поля shipping_address. Как я могу этого добиться?

serializer

class UserSerializer(serializers.ModelSerializer):
    """Serializer for the users object"""

    class Meta:
        model = get_user_model()
        fields = ('email', 'password', 'first_name', 'last_name', 'mailing_address', 'shipping_address', 'phone', 'is_active', 'is_staff', 'is_approver')

    def create(self, validated_data):
        """Create a new user with encrypted password and return it"""
        return get_user_model().objects.create_user(**validated_data)

модели

   class Address(models.Model):
        first_address = models.CharField(max_length=255, blank=True, default='')
        second_address = models.CharField(max_length=255, blank=True, default='')
        city = models.CharField(max_length=255, blank=True, default='')
        state = models.CharField(max_length=255, blank=True, default='')
        zip = models.CharField(max_length=255, blank=True, default='')
    
    
    class Phone(models.Model):
        phone_number = PhoneField(blank=True, help_text='Contact phone number')
    
    
    class ShippingAddress(models.Model):
        first_address = models.CharField(max_length=255, blank=True, default='')
        second_address = models.CharField(max_length=255, blank=True, default='')
        city = models.CharField(max_length=255, blank=True, default='')
        state = models.CharField(max_length=255, blank=True, default='')
        zip = models.CharField(max_length=255, blank=True, default='')
    
    
    class User(AbstractBaseUser, PermissionsMixin):
        """Custom user model that suppors using email instead of username"""
        email = models.EmailField(max_length=255, unique=True)
        first_name = models.CharField(max_length=255, blank=True, default='')
        last_name = models.CharField(max_length=255, blank=True, default='')
        password = forms.CharField(widget=forms.PasswordInput)
        phone = models.ForeignKey(Phone, on_delete=models.CASCADE, null=True, blank=True)
        mailing_address = models.ForeignKey(Address, on_delete=models.CASCADE, null=True, blank=True)
        shipping_address = models.ForeignKey(ShippingAddress, on_delete=models.CASCADE, null=True, blank=True)
        is_active = models.BooleanField(default=True)
        is_staff = models.BooleanField(default=False)
        is_approver = models.BooleanField(default=False)
    
        objects = UserManager()
    
        USERNAME_FIELD = 'email'

enter image description here

Как отобразить поля других моделей в представлении создания в Django?

Однако здесь следует быть осторожным: Django Rest Framework предоставляет удобный веб-интерфейс для взаимодействия с REST API, который вы создаете. Однако это не единственный и, возможно, даже не самый распространенный способ взаимодействия с вашим API.

На самом деле, пользователи вашего приложения НЕ ДОЛЖНЫ ВИДЕТЬ ЭТОТ ВЕБ ИНТЕРФЕЙС. Вместо этого, вы должны создать свой собственный интерфейс, который взаимодействует с вашим REST API. Это даст вам гибкость в создании любых форм в HTML, которые вы хотите.

Например, вы можете создать единую форму со всеми полями пользователя вместе с полями для адреса доставки и отдельного адреса для выставления счета. Затем вы пишете JavaScript во фронт-энде для создания объектов Address с помощью POST-запросов к вашему API. POST-запрос вернет идентификатор нового объекта адреса. Затем вы делаете еще один POST-запрос для создания пользователя с этим id и всеми другими полями пользователя.

Попутно заметим, что нет необходимости в модели ShippingAddress, которая имеет точно такие же поля, как и ваша модель Address. Просто используйте Address для всех полей адреса:

        mailing_address = models.ForeignKey(Address, on_delete=models.CASCADE, null=True, blank=True)
        shipping_address = models.ForeignKey(Address, on_delete=models.CASCADE, null=True, blank=True)

Думаю, вы можете использовать вложенный сериализатор DRF с возможностью записи.

Что-то вроде этого (еще не тестировал):

  • Добавьте сериализатор для модели Address:

    class AddressSerializer(serializers.ModelSerializer):
        class Meta:
            model = Address
            fields = '__all__'
    
  • И измените ваш текущий сериализатор для модели User (как @Code-Apprentice сказал в комментарии, вы можете использовать одну и ту же модель Address для mailing_address и shipping_address):

    class UserSerializer(serializers.ModelSerializer):
        """Serializer for the users object"""
        mailing_address = AddressSerializer()
        shipping_address = AddressSerializer()
    
        class Meta:
            model = get_user_model()
            fields = ('email', 'password', 'first_name', 'last_name', 'mailing_address', 'shipping_address', 'phone', 'is_active', 'is_staff', 'is_approver')
    
        def create(self, validated_data):
            """Create a new user with encrypted password and return it""" 
            mailing_address = Address.objects.create(**validated_data.pop('mailing_address'))
            shipping_address = Address.objects.create(**validated_data.pop('shipping_address'))
            return get_user_model().objects.create_user(mailing_address=mailing_address, shipping_address=shipping_address, **validated_data)
    
Вернуться на верх