fix OneToOneField without related_name

This commit is contained in:
Maxim Kurnikov
2019-07-19 18:30:12 +03:00
parent fc9843bea6
commit fee4aad3d0
3 changed files with 41 additions and 27 deletions

View File

@@ -1,7 +1,8 @@
from abc import ABCMeta, abstractmethod
from abc import ABCMeta, abstractmethod
from typing import cast
from typing import cast, Type
from django.db.models.base import Model
from django.db.models.fields.related import ForeignKey
from django.db.models.fields.reverse_related import ManyToManyRel, ManyToOneRel, OneToOneRel
from mypy.newsemanal.semanal import NewSemanticAnalyzer
@@ -45,9 +46,15 @@ class ModelClassInitializer(metaclass=ABCMeta):
var.is_inferred = True
self.model_classdef.info.names[name] = SymbolTableNode(MDEF, var, plugin_generated=True)
@abstractmethod
def run(self) -> None:
raise NotImplementedError()
model_cls = self.django_context.get_model_class_by_fullname(self.model_classdef.fullname)
if model_cls is None:
return
self.run_with_model_cls(model_cls)
@abstractmethod
def run_with_model_cls(self, model_cls):
pass
class InjectAnyAsBaseForNestedMeta(ModelClassInitializer):
@@ -63,7 +70,7 @@ class InjectAnyAsBaseForNestedMeta(ModelClassInitializer):
to get around incompatible Meta inner classes for different models.
"""
def run(self) -> None:
def run_with_model_cls(self, model_cls: Type[Model])-> None:
meta_node = helpers.get_nested_meta_node_for_current_class(self.model_classdef.info)
if meta_node is None:
return None
@@ -71,11 +78,7 @@ class InjectAnyAsBaseForNestedMeta(ModelClassInitializer):
class AddDefaultPrimaryKey(ModelClassInitializer):
def run(self) -> None:
model_cls = self.django_context.get_model_class_by_fullname(self.model_classdef.fullname)
if model_cls is None:
return
def run_with_model_cls(self, model_cls: Type[Model])-> None:
auto_field = model_cls._meta.auto_field
if auto_field and not self.model_classdef.info.has_readable_member(auto_field.attname):
# autogenerated field
@@ -88,11 +91,7 @@ class AddDefaultPrimaryKey(ModelClassInitializer):
class AddRelatedModelsId(ModelClassInitializer):
def run(self) -> None:
model_cls = self.django_context.get_model_class_by_fullname(self.model_classdef.fullname)
if model_cls is None:
return
def run_with_model_cls(self, model_cls: Type[Model])-> None:
for field in model_cls._meta.get_fields():
if isinstance(field, ForeignKey):
rel_primary_key_field = self.django_context.get_primary_key_field(field.related_model)
@@ -104,11 +103,7 @@ class AddRelatedModelsId(ModelClassInitializer):
class AddManagers(ModelClassInitializer):
def run(self):
model_cls = self.django_context.get_model_class_by_fullname(self.model_classdef.fullname)
if model_cls is None:
return
def run_with_model_cls(self, model_cls: Type[Model])-> None:
for manager_name, manager in model_cls._meta.managers_map.items():
if manager_name not in self.model_classdef.info.names:
manager_fullname = helpers.get_class_fullname(manager.__class__)
@@ -126,14 +121,17 @@ class AddManagers(ModelClassInitializer):
# add related managers
for relation in self.django_context.get_model_relations(model_cls):
attname = relation.related_name
attname = relation.get_accessor_name()
if attname is None:
attname = relation.name + '_set'
# no reverse accessor
continue
related_model_info = self.lookup_class_typeinfo_or_incomplete_defn_error(relation.related_model)
if isinstance(relation, OneToOneRel):
self.add_new_node_to_model_class(attname, Instance(related_model_info, []))
continue
if isinstance(relation, (ManyToOneRel, ManyToManyRel)):
manager_info = self.lookup_typeinfo_or_incomplete_defn_error(fullnames.RELATED_MANAGER_CLASS_FULLNAME)
self.add_new_node_to_model_class(attname,
@@ -142,11 +140,7 @@ class AddManagers(ModelClassInitializer):
class AddExtraFieldMethods(ModelClassInitializer):
def run(self):
model_cls = self.django_context.get_model_class_by_fullname(self.model_classdef.fullname)
if model_cls is None:
return
def run_with_model_cls(self, model_cls: Type[Model])-> None:
# get_FOO_display for choices
for field in self.django_context.get_model_fields(model_cls):
if field.choices:
@@ -178,7 +172,7 @@ class AddExtraFieldMethods(ModelClassInitializer):
class AddMetaOptionsAttribute(ModelClassInitializer):
def run(self):
def run_with_model_cls(self, model_cls: Type[Model])-> None:
if '_meta' not in self.model_classdef.info.names:
options_info = self.lookup_typeinfo_or_incomplete_defn_error(fullnames.OPTIONS_CLASS_FULLNAME)
self.add_new_node_to_model_class('_meta',