Как отобразить поля других моделей в представлении создания в 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'
Как отобразить поля других моделей в представлении создания в 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)
