首页 > 解决方案 > 获取 RelatedObjectDoesNotExist 错误访问自定义表单上的字段

问题描述

我对 Django(和一般的 python)比较陌生,我正在从事我自己没有编码的项目。

具体来说,我试图通过保存表单中的一些信息,POST但是RelatedObjectDoesNotExist在访问user自定义Profile模型中定义的字段时出现错误,我不明白为什么。

这是我的views.py

def conferma(request):
    family = request.user.profile.family  # cannot be null
    already_confirmed = request.user.profile.conferma_inviata

    if(already_confirmed == False):

        ProfileFormSet = modelformset_factory(
            Profile, form=ConfirmForm, extra=0)

        if request.method == 'POST':
            formset = ProfileFormSet(
                request.POST, queryset=Profile.objects.filter(family=family))
            if formset.is_valid():
                for form in formset:
                    f = form.save(commit=False)
                    f.conferma_inviata = True
                    f.save()

如果我尝试访问f.user,我会收到一个RelatedObjectDoesNotExist错误,我需要该信息来保存表单。

这是我的forms.py:

class ConfirmForm(forms.ModelForm):
    class Meta:
        model = Profile
        fields = ('user', 'conferma_pranzo',
                  'conferma_sera', 'conferma_inviata',)

    def __init__(self, *args, **kwargs):
        super(ConfirmForm, self).__init__(*args, **kwargs)
        self.fields['user'].required = False
        self.fields['conferma_inviata'].required = False

这是我的models.py

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    full_day = models.BooleanField(default=True)
    family = models.TextField(max_length=100, blank=True)
    conferma_pranzo = models.BooleanField(default=False)
    conferma_sera = models.BooleanField(default=False)
    conferma_inviata = models.BooleanField(default=False)

    def __str__(self):
        return self.user.first_name + ' ' + self.user.last_name

我已经检查了数据库,但Profile记录已正确存储并带有适当的userd_id参考。

我究竟做错了什么?

编辑这是当我尝试user通过调试器的变量检查器查看表单上的字段时的回溯:

Traceback (most recent call last):
  File "/home/simone/.vscode/extensions/ms-python.python-2020.9.114305/pythonFiles/lib/python/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_resolver.py", line 193, in _get_py_dictionary
    attr = getattr(var, name)
  File "/home/simone/.local/lib/python3.7/site-packages/django/db/models/fields/related_descriptors.py", line 198, in __get__
    "%s has no %s." % (self.field.model.__name__, self.field.name)
invitations.models.Profile.user.RelatedObjectDoesNotExist: Profile has no user.

标签: pythonpython-3.xdjango

解决方案


当关系不存在时,OneToOneField 反向关系会在 django 中引发错误(与返回 None 类型的 ForeignKeys 相反)。

如果没有回溯,我不完全确定您的错误在哪里,但是这样的事情可能会有所帮助:

模型.py:

from django.db import IntegrityError

class Profile(models.Model):

    # add related name argument to user field for reverse accessing:
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='user_profile')
    ...

class User(...):
    ...
    
    # return a None type when a reverse relation does not exist (instead of an IntegrityError)
    @property
    def profile(self): 
        try: return self.user_profile
        except IntegrityError: return None

视图.py:

def conferma(request):

    # do something if the user has a profile:
    if request.user.profile:
        ...

    # do something else if the user does not have a profile:
    else:
        ...

推荐阅读