【问题标题】:Django: Cannot save related model in CBVDjango:无法在 CBV 中保存相关模型
【发布时间】:2012-09-12 05:29:24
【问题描述】:

我有两个与this case 非常相似的模型:

class Location(models.Model):
    city = models.CharField(max_length=20)
    address = models.CharField(max_length=30)

class Event(models.Model):
    location = models.ForeignKey(Location)    
    date = models.DateField()
    user = models.ForeignKey(User)

我尝试将这些对象保存在表单中:

class EventForm(forms.ModelForm):
    city = forms.CharField(label=_('City'), max_length=30)
    address = forms.CharField(label=_('Street'), max_length=30, required=False)

    class Meta:
        model = Event

    def __init__(self, *args, **kwargs)
        super(EventForm, self).__init__(*args, **kwargs)
        try:
            self.fields['city'].initial = self.instance.location.city
            self.fields['address'].initial = self.instance.location.street
        except AttributeError:
            pass

    def save(self, commit=True):
        event = super(EventForm, self).save(commit=False)
        location = event.location
        location.city = self.cleaned_data['city']
        location.address = self.cleaned_data['address']
        location.save()
        return event

这会引发错误'NoneType' object has no attribute 'city'

我还尝试在 CBV 中保存位置:

class EventEdit(UpdateView):
    model = Event

    def form_valid(self, form):
        event = form.save(commit=False)
        location = event.location
        location.city = self.cleaned_data['city']
        location.address = self.cleaned_data['address']
        location.save()
        event.save()
        return HttpResponseRedirect(self.get_success_url())

同样的错误'NoneType' object has no attribute 'city'

在基于类的视图中保存相关对象的正确方法是什么?

更新

我必须补充一点,我正在询问更新分配给事件的现有位置。完全按照 Rohan 的建议,在 EventCreate(CreateView) 中添加新的活动地点。

class EventCreate(CreateView):
    def form_valid(self, form):
        self.object = form.save(commit=False)
        location = Location()
        location.address = self.request.POST['address']
        location.city = self.request.POST['city']
        location.save()
        self.object.location = location
        self.object.save()
        return HttpResponseRedirect(self.get_success_url())

【问题讨论】:

    标签: django django-class-based-views


    【解决方案1】:

    在您的 save 方法中,event.location 将是 None。您需要创建location 实例,然后保存。

    更新:用于保存现有对象:

    我不确定您对UpdateView 的实施是否是阅读Generic views - Models 后的一种方式

    我建议将视图更改为:

    class EventEdit(UpdateView):
        model = Event
    
        def form_valid(self, form):
            #instance trying to update
            event = form.instance 
            location = event.location
            if location == None:
                location = Location()
            location.city = self.cleaned_data['city']
            location.address = self.cleaned_data['address']
            location.save()
            event.location = location
            #event.save() instead of this do
            super(EventEdit, self).form_valid(form)
            return HttpResponseRedirect(self.get_success_url())
    

    旧解决方案:

    我会将保存方法更改为

    def save(self, commit=True):
        event = super(EventForm, self).save(commit=False)
        location = Location()
        location.city = self.cleaned_data['city']
        location.address = self.cleaned_data['address']
        location.save()
        event.location = location
        event.save()
        return event
    

    【讨论】:

    • 感谢您的回复!这正是我在EventCreate(CreateView).form_valid() 中所做的,并且有效。但我需要获取并更新已分配给事件的现有位置。
    • 尝试了更新的解决方案,现在它会在每次更新时创建新的 Location 对象。似乎它无法从event.location 以及我的版本中获取位置(总是无)。
    • @VladT。您是否尝试过从表单中删除 save() 方法,我认为不需要。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-12
    • 2021-12-17
    • 2021-11-01
    • 2019-04-20
    • 2015-12-23
    • 2022-01-24
    • 2019-02-02
    相关资源
    最近更新 更多