Скажем, я использую значение по умолчанию auth.models.User
плюс мое пользовательское Profile
и Address
модели, которые похожи на это:
class Profile(models.Model):
user = models.OneToOneField(User)
primary_phone = models.CharField(max_length=20)
address = models.ForeignKey("Address")
class Address(models.Model):
country = CountryField(default='CA')
province = CAProvinceField(default='BC')
city = models.CharField(max_length=80)
postal_code = models.CharField(max_length=6)
street1 = models.CharField(max_length=80)
street2 = models.CharField(max_length=80, blank=True, null=True)
street3 = models.CharField(max_length=80, blank=True, null=True)
Теперь я хочу создать форму регистрации. Я мог создать a ModelForm
на основе User
но это не будет включать поля для Profile
и Address
(которые требуются). Таким образом, что лучший способ состоит в том, чтобы пойти о создании этой формы? Если я даже использую ModelForm
вообще?
Кроме того, как я использовал бы ту же форму для редактирования сложного объекта? Я мог легко пасовать назад экземпляр Профиля к нему, который содержит ссылки на необходимые объекты Адреса и Профиля, но как я заставляю его заполнять поля для меня?
А как насчет использования трех отдельных ModelForm
. Один для адреса
, один для пользователя
и один для профиля
, но с:
class ProfileForm(ModelForm):
class Meta:
model = Profile
exclude = ('user', 'address',)
Затем обработайте эти 3 формы отдельно в ваших представлениях. В частности, для ProfileForm
используйте save
с commit = False
, чтобы обновить поле пользователя
и адрес
на экземпляре. :
# ...
profile_form = ProfileForm(request.POST)
if profile_form.is_valid():
profile = profile_form.save(commit=False)
# `user` and `address` have been created previously
# by saving the other forms
profile.user = user
profile.address = address
Не стесняйтесь использовать здесь транзакции, чтобы гарантировать, что строки будут вставлены только тогда, когда 3 формы действительны.
Думаю, вы ищете встроенные наборы форм с модельными формами. Это поможет вам работать с несколькими формами на одной странице, а также позаботится об отношениях внешних ключей.
Обновление:
Возможно, этот вопрос вам тоже поможет: Django: несколько моделей в одном шаблоне с использованием форм
Сначала вам следует изучить официально рекомендуемый способ расширения модели User, как показано в документации, которая, как я полагаю, взята непосредственно из личного блога руководителя проекта на эту тему. (Сама статья в блоге уже довольно старая)
Что касается вашей проблемы с формами, посмотрите на собственное многоразовое приложение django-profiles менеджера проекта и посмотрите, решит ли изучение кода вашу проблему. В частности, эти функции и представления, в которых они используются.
Отредактировано для добавления:
Я немного изучил этот вопрос (так как мне самому нужно было это сделать). Кажется, будет достаточно чего-то вроде этого:
# apps.profiles.models
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
...
birth_date = models.DateField(blank=True, null=True)
joined = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = 'user profile'
verbose_name_plural = 'user profiles'
db_table = 'user_profiles'
class Address(models.Model):
user = models.ForeignKey(UserProfile)
...
# apps.profiles.forms
from django import forms
from django.forms import ModelForm
from django.forms.models import inlineformset_factory
from django.contrib.auth.models import User
from apps.profiles.models import UserProfile, Address
class UserForm(ModelForm):
class Meta:
model = User
...
class UserProfileForm(ModelForm):
class Meta:
model = UserProfile
...
AddressFormSet = inlineformset_factory(UserProfile, Address)
Я использовал "..." для вырезания содержимого в коде выше. Я еще не проверял это, но, просмотрев примеры и документацию по формам, я считаю, что это правильно.
Обратите внимание, что я поместил FK из модели Address в UserProfile, а не наоборот, как в вашем вопросе. Я считаю, что для корректной работы инлайн-форм это необходимо.
Затем, конечно, в ваших представлениях и шаблонах вы будете обрабатывать UserForm, UserProfileForm и AddressFormSet отдельно, но все они могут быть вставлены в одну форму.