Django моделирует с отношениями OneToOne?

Скажем, я использую значение по умолчанию 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 вообще?

Кроме того, как я использовал бы ту же форму для редактирования сложного объекта? Я мог легко пасовать назад экземпляр Профиля к нему, который содержит ссылки на необходимые объекты Адреса и Профиля, но как я заставляю его заполнять поля для меня?

7
задан Jiaaro 23 November 2011 в 04:19
поделиться

3 ответа

А как насчет использования трех отдельных 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 формы действительны.

8
ответ дан 6 December 2019 в 21:13
поделиться

Думаю, вы ищете встроенные наборы форм с модельными формами. Это поможет вам работать с несколькими формами на одной странице, а также позаботится об отношениях внешних ключей.

Обновление:

Возможно, этот вопрос вам тоже поможет: Django: несколько моделей в одном шаблоне с использованием форм

1
ответ дан 6 December 2019 в 21:13
поделиться

Сначала вам следует изучить официально рекомендуемый способ расширения модели 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 отдельно, но все они могут быть вставлены в одну форму.

3
ответ дан 6 December 2019 в 21:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: