В проекте Django существует модель Family
, определенная следующим образом:
class Family(BaseFamily):
employee_first_name = models.CharField(max_length=255, blank=True)
employee_last_name = models.CharField(max_length=255, blank=True)
partner_first_name = models.CharField(max_length=255, blank=True)
partner_last_name = models.CharField(max_length=255, blank=True)
, где BaseFamily
имеет внешний ключ package
и lucy_guide
:
class BaseFamily(TimeStampedModel):
package = models.ForeignKey('lucy_web.Package',
models.SET_NULL,
blank=True,
null=True)
lucy_guide = models.ForeignKey(
User,
blank=True,
null=True,
related_name='lucy_guide_%(class)s',
limit_choices_to={'is_staff': True})
Модель Package
, в свою очередь, связана с Company
:
class Package(TimeStampedModel):
company = models.ForeignKey('lucy_web.Company')
, а Company
, в свою очередь, имеет lucy_guide
и default_package
:
class Company(TimeStampedModel):
lucy_guide = models.ForeignKey(
User,
blank=True,
null=True,
related_name='lucy_guide_%(class)s',
limit_choices_to={'is_staff': True})
default_package = models.OneToOneField(
Package,
blank=True,
null=True,
related_name='default_for_%(class)s')
Теперь у меня есть шаблон, который использует следующий тег шаблона edit_view_family_heading
:
from django import template
register = template.Library()
@register.simple_tag
def edit_view_family_heading(family):
heading = [family.employee_first_name]
if family.employee_last_name != family.partner_last_name:
heading.append(family.employee_last_name)
heading.extend([
'&',
family.partner_first_name,
family.partner_last_name
])
heading = [e for e in heading if e]
if heading[0] == '&':
heading.pop(0)
if heading and heading[-1] == '&':
heading.pop()
if heading:
if family.lucy_guide:
heading.append(f'({family.lucy_guide.first_name})')
return ' '.join(heading)
else:
return family.id
Однако, если я пытаюсь отобразить шаблон, я получаю следующееошибка:
Template error:
In template /Users/kurtpeek/Documents/Dev/lucy2/lucy-web/dashboard/templates/dashboard.html, error at line 0
User matching query does not exist. 1 : {% load static %}
2 : {% load sass_tags %}
3 : {% load compress %}
4 : {% load google_analytics %}
5 : {% load active_page %}
6 :
7 : <!DOCTYPE html>
8 : <html lang="en">
9 : <head>
10 : <title>Cleo Admin | {% block page_title %}{% endblock %}</title>
Traceback:
File "/Users/kurtpeek/Documents/Dev/lucy2/lucy-web/venv/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py" in __get__
178. rel_obj = getattr(instance, self.cache_name)
During handling of the above exception ('Family' object has no attribute '_lucy_guide_cache'), another exception occurred:
File "/Users/kurtpeek/Documents/Dev/lucy2/lucy-web/venv/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
41. response = get_response(request)
File "/Users/kurtpeek/Documents/Dev/lucy2/lucy-web/venv/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
217. response = self.process_exception_by_middleware(e, request)
File "/Users/kurtpeek/Documents/Dev/lucy2/lucy-web/venv/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
215. response = response.render()
File "/Users/kurtpeek/Documents/Dev/lucy2/lucy-web/venv/lib/python3.6/site-packages/django/template/response.py" in render
107. self.content = self.rendered_content
File "/Users/kurtpeek/Documents/Dev/lucy2/lucy-web/venv/lib/python3.6/site-packages/django/template/response.py" in rendered_content
84. content = template.render(context, self._request)
File "/Users/kurtpeek/Documents/Dev/lucy2/lucy-web/venv/lib/python3.6/site-packages/django/template/backends/django.py" in render
66. return self.template.render(context)
File "/Users/kurtpeek/Documents/Dev/lucy2/lucy-web/venv/lib/python3.6/site-packages/django/template/base.py" in render
207. return self._render(context)
File "/Users/kurtpeek/Documents/Dev/lucy2/lucy-web/venv/lib/python3.6/site-packages/django/template/base.py" in _render
199. return self.nodelist.render(context)
File "/Users/kurtpeek/Documents/Dev/lucy2/lucy-web/venv/lib/python3.6/site-packages/django/template/base.py" in render
990. bit = node.render_annotated(context)
File "/Users/kurtpeek/Documents/Dev/lucy2/lucy-web/venv/lib/python3.6/site-packages/django/template/base.py" in render_annotated
957. return self.render(context)
File "/Users/kurtpeek/Documents/Dev/lucy2/lucy-web/venv/lib/python3.6/site-packages/django/template/loader_tags.py" in render
177. return compiled_parent._render(context)
File "/Users/kurtpeek/Documents/Dev/lucy2/lucy-web/venv/lib/python3.6/site-packages/django/template/base.py" in _render
199. return self.nodelist.render(context)
File "/Users/kurtpeek/Documents/Dev/lucy2/lucy-web/venv/lib/python3.6/site-packages/django/template/base.py" in render
990. bit = node.render_annotated(context)
File "/Users/kurtpeek/Documents/Dev/lucy2/lucy-web/venv/lib/python3.6/site-packages/django/template/base.py" in render_annotated
957. return self.render(context)
File "/Users/kurtpeek/Documents/Dev/lucy2/lucy-web/venv/lib/python3.6/site-packages/django/template/loader_tags.py" in render
72. result = block.nodelist.render(context)
File "/Users/kurtpeek/Documents/Dev/lucy2/lucy-web/venv/lib/python3.6/site-packages/django/template/base.py" in render
990. bit = node.render_annotated(context)
File "/Users/kurtpeek/Documents/Dev/lucy2/lucy-web/venv/lib/python3.6/site-packages/django/template/base.py" in render_annotated
957. return self.render(context)
File "/Users/kurtpeek/Documents/Dev/lucy2/lucy-web/venv/lib/python3.6/site-packages/django/template/library.py" in render
203. output = self.func(*resolved_args, **resolved_kwargs)
File "/Users/kurtpeek/Documents/Dev/lucy2/lucy-web/dashboard/templatetags/edit_view_family_heading.py" in edit_view_family_heading
28. if family.lucy_guide:
File "/Users/kurtpeek/Documents/Dev/lucy2/lucy-web/venv/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py" in __get__
184. rel_obj = self.get_object(instance)
File "/Users/kurtpeek/Documents/Dev/lucy2/lucy-web/venv/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py" in get_object
159. return qs.get(self.field.get_reverse_related_filter(instance))
File "/Users/kurtpeek/Documents/Dev/lucy2/lucy-web/venv/lib/python3.6/site-packages/django/db/models/query.py" in get
380. self.model._meta.object_name
Exception Type: DoesNotExist at /dashboard/families/763/case-management
Exception Value: User matching query does not exist.
Я пытался сузить проблему с этими модульными тестами, но все они проходят:
from django.test import TestCase
from django.urls import reverse
from dashboard.tests.utils import AccountMixin
from dashboard.templatetags.edit_view_family_heading import edit_view_family_heading
from lucy_web.test_factories import FamilyFactory, UserFactory
from lucy_web.models import Family
class FamilyEditTest(TestCase, AccountMixin):
def setUp(self):
self.login_user(UserFactory(is_superuser=True))
def test_case_management_with_lucy_guide_defined(self):
family = FamilyFactory()
response = self.client.get(
reverse('dashboard:family', kwargs={'pk': family.id, 'tab': 'case-management'}))
self.assertTemplateUsed(response, 'families/edit.html')
def test_case_management_without_lucy_guide_defined(self):
family = Family()
family.save()
self.assertIs(family.lucy_guide, None)
response = self.client.get(
reverse('dashboard:family', kwargs={'pk': family.id, 'tab': 'case-management'}))
self.assertTemplateUsed(response, 'families/edit.html')
class TestFamilyHeading(TestCase):
def test_edit_view_family_heading(self):
family = FamilyFactory(
employee_first_name="Shannon",
employee_last_name="Spanhake",
partner_first_name="Aaron",
partner_last_name="Levie",
lucy_guide=UserFactory(first_name="Rebekah"))
heading = edit_view_family_heading(family)
self.assertEqual(
heading,
"Shannon Spanhake & Aaron Levie (Rebekah)")
def test_edit_view_family_heading_no_lucy_guide(self):
family = FamilyFactory(package=None)
self.assertIs(family.lucy_guide, None)
heading = edit_view_family_heading(family)
self.assertEqual(
heading,
f"{family.employee_first_name} {family.employee_last_name} & "
f"{family.partner_first_name} {family.partner_last_name}")
Другими словами, представление использует правильный шаблони тег шаблона работает, как и ожидалось, при тестировании в качестве обычной функции, даже если в семействе нет lucy_guide
.
Я подозреваю, что моя база данных находится в "странном" состоянии и что где-то в этой взаимосвязанной цепочкеВ моделях чего-то не хватает, но я изо всех сил пытаюсь сузить, что.Любые предложения по устранению этой ошибки?
Обновление
Глядя на базу данных (с pgAdmin 4), может показаться, что рассматриваемый Family
имеет lucy_guide_id
:

Однако в таблице auth_user
нет строки, соответствующей этому id
:

Я подозреваю, что это связано с опцией on_delete=models.SET_NULL
для внешнего ключа package
, но я ничего не вижу в документации (https://docs.djangoproject.com/en/2.0/ref/models/fields/#django.db.models.ForeignKey.on_delete) это указывает на то, что любой из параметров позволил бы базе данных войти в такое «поврежденное» состояние.
Есть какие-нибудь идеи, как база данных попала в это состояние и как я мог воспроизвести эту ошибку в модульном тесте?