Модели Django с отношениями OneToOne? - PullRequest
7 голосов
/ 13 февраля 2010

Допустим, я использую 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)

Теперь я хочу создать регистрационную форму. Я мог бы создать ModelForm на основе User, но это не будет включать поля для Profile и Address (которые требуются). Итак, как лучше всего построить эту форму? Должен ли я вообще использовать ModelForm?

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

Ответы [ 3 ]

8 голосов
/ 15 февраля 2010

Как насчет использования 3 отдельных ModelForm. Один для Address, один для User и один для Profile, но с:

class ProfileForm(ModelForm):
  class Meta:
    model = Profile
    exclude = ('user', 'address',)

Затем обработайте эти 3 формы отдельно в ваших представлениях. В частности, для ProfileForm используйте save с commit=False для обновления поля user и address в экземпляре:

# ...
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 формы действительны.

3 голосов
/ 13 февраля 2010

Вы должны сначала изучить официально рекомендованный способ расширения модели User, , как видно из документов , что, как мне кажется, взято непосредственно из личного блога руководителя проекта по теме, (Фактическая статья в блоге довольно старая, сейчас)

Что касается вашей реальной проблемы с формами, взгляните на собственное приложение менеджера проекта django-profile , предназначенное для повторного использования, и посмотрите, решает ли просмотр кода проблему. В частности эти функции и представления , в которых они используются.

Отредактировано для добавления:

Я немного разбирался в этом (так как мне нужно было сделать это самому). Кажется, что-то вроде этого будет достаточно:

# 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 по отдельности, но все они могут быть вставлены в одну форму.

1 голос
/ 13 февраля 2010

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

Обновление:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...