#python #python-3.x #django
#python #python-3.x #django
Вопрос:
Я относительно новичок в 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.
Ответ №1:
Обратные отношения OneToOneField выдают ошибки в django, когда отношение не существует (в отличие от ForeignKeys, которые возвращают тип None).
Без обратной трассировки я не совсем уверен, где у вас ошибка, однако что-то вроде этого может помочь:
models.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
views.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:
...
Комментарии:
1. Привет, Даниэль, спасибо за ваш ответ! Я приложил точную обратную трассировку в исходном сообщении. Я не понимаю, почему я получаю эту ошибку, поскольку я пытаюсь получить доступ к пользователю из формы профиля. Профиль в request.user присутствует (а также с атрибутом user), но меня интересуют профили набора форм, которые не содержат пользователей.
Ответ №2:
Из того, что я понял до сих пор user
, данные не отправляются в POST внутри Profile
in the ConfirmForm
.
Это шаблон, из которого поступает сообщение:
<form method="post">
{% csrf_token %}
{{ formset.management_form }}
<table align="center" class="w3-table-all" style="width:100%; max-width:400px">
<tr>
<th>Nome</th>
{% if user.profile.full_day %}
<th class="w3-center">Conferma pranzo</th>
{% endif %}
<th class="w3-center">Conferma sera (dalle 18:30)</th>
</tr>
{% for form in formset %}
<tr>
<td>{{ form.instance.user.first_name }}</td>
{% if user.profile.full_day %}
<td class="w3-center">{{ form.conferma_pranzo }}</td>
{% endif %}
<td class="w3-center">{{ form.conferma_sera }}</td>
{{form.id}}
</tr>
{% endfor %}
</table>
<br>
<input type="submit" value="Invia conferma">
</form>
Как я могу добавить эту информацию?