【问题标题】:Saving OnetoOne field manually in django在 django 中手动保存 OnetoOne 字段
【发布时间】:2015-02-01 11:34:11
【问题描述】:

我有以下型号:

class Person(User):
    first_name = models.CharField(verbose_name=_('first name'), max_length=30)
    last_name = models.CharField(verbose_name=_('last name'), max_length=30)

class Service(models.Model):
    person = models.ForeignKey(Person, related_name='services')
    price_from = models.DecimalField(_('price form'), max_digits=10, decimal_places=2, validators=[MinValueValidator(Decimal('0.01'))])
    price_to = models.DecimalField(_('price to'), max_digits=10, decimal_places=2, validators=[MinValueValidator(Decimal('0.01'))])

class WorkPlace(models.Model):
    service = models.OneToOneField('Service', related_name='work_place', primary_key=True)
    city = CharField(verbose_name=_('city'), max_length=255)
    street = CharField(verbose_name=_('street'), max_length=255)

我还在管理员中注册了Person,并让Service 成为内联管理员。 由于设计原因,城市和地址作为多值字段输入。 问题是我无法手动保存 WorkPlace。 以下是表格:

class WorkPlaceForm(forms.ModelForm):
    class Meta:
        model = WorkPlace
        fields = '__all__'

class PersonForm(forms.ModelForm):
    class Meta:
        model = Person
        fields = '__all__'

class ServiceForm(forms.ModelForm):
    class Meta:
        fields = '__all__'
        model = Service

    multi_work_place = MyMultiValueField()

    def save(self, commit=True):
        service = super(ServiceForm, self).save(commit=commit)
        if self.cleaned_data['multi_work_place']:
            work_place = WorkPlace(**{
                'city': self.cleaned_data['multi_work_place'][0],
                'street': self.cleaned_data['multi_work_place'][1],
            })
            # when there is brand new object is created, there is no service.pk
            work_place.service = service # how???
            work_place.save()
        return service

此外,如果我在新对象上写service = super(ServiceForm, self).save(commit=True),这将引发错误,因为没有创建Person

我该如何解决这个问题?回想一下,我在管理部门工作。

【问题讨论】:

  • 这段代码应该已经可以工作了,因为service 是从超类保存返回的服务对象。当你尝试时究竟会发生什么?
  • “person_id 列不能为空”,如果我使用 service = super(ServiceForm, self).save(commit=True),因为真的,还没有成员。一般来说,Django 是如何做这些事情的。如果我使用 service = super(ServiceForm, self).save(commit=commit),那么在调试器中,commit 似乎是 False 并且服务未保存,这会导致 work_place.save() 引发“service_id column can not be null”
  • 但是 person_id 是完全独立的关系,所以这个错误与设置服务/工作场所无关。

标签: django django-models django-forms django-admin


【解决方案1】:
class ServiceForm(forms.ModelForm):
    class Meta:
        fields = '__all__'
        model = Service

    multi_work_place = MyMultiValueField()

    def save(self, commit=True):
        service = super(ServiceForm, self).save(commit=False)
        service.member_id = service.member.pk # here is the key command
        service.save()
        if self.cleaned_data['multi_work_place']:
            work_place = WorkPlace(**{
                'city': self.cleaned_data['multi_work_place'][0],
                'street': self.cleaned_data['multi_work_place'][1],
            })
            # when there is brand new object is created, there is no service.pk
            work_place.service = service # how???
            work_place.save()
        return service

我只需要将成员pk添加到服务模型中

【讨论】:

  • service.save() 我的解决方案假设您在表单数据中传递了正确的 member_id 分配。
  • 这就是问题所在。所以这不能是一个假设。
【解决方案2】:

试试这个:

class ServiceForm(forms.ModelForm):
    class Meta:
        fields = '__all__'
        model = Service

    multi_work_place = MyMultiValueField()

    def save(self, commit=True):
        service = save_instance(self, self.instance, self._meta.fields,
                             fail_message, commit, self._meta.exclude,
                             construct=False)
        service.save()
        if self.cleaned_data['multi_work_place']:
            work_place = WorkPlace(**{
                'city': self.cleaned_data['multi_work_place'][0],
                'street': self.cleaned_data['multi_work_place'][1],
            })
            # when there is brand new object is created, there is no service.pk
            work_place.service = service 
            work_place.save()
        return service

【讨论】:

  • save_instance 不是 ServiceForm 的方法
  • 你需要form django.forms import save_instance
  • 在您当前的代码中,您也许可以照常调用 Super 函数,然后在使用它之前执行service.save()。我以前没有尝试过那条路线; save_instance 是def save(..) 通常所做的,我只是从那里复制的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-15
  • 1970-01-01
  • 1970-01-01
  • 2016-06-10
  • 2016-11-10
  • 1970-01-01
  • 2012-05-25
相关资源
最近更新 更多