无法从django rest-framework中的其他序列化程序导入序列化程序?

时间:2017-02-04 22:52:03

标签: python django serialization django-rest-framework python-import

问题

我有2个型号,潜在客户和笔记。我希望领导能够有一个或多个笔记。我使用了通用外键,因为我想为将来做好计划,例如可以指定一个人来说个人或会议。

按照django rest框架和Rest Framework通用关系的说明,我试图从另一个中导入一个序列化程序,以使反向关系成为可能。

错误

我无法在两个文件中导入序列化程序(从另一个文件中调用一个序列化程序),因为我得到了:

a[1] = b

很奇怪,因为如果我打开django shell并运行以下内容,我就可以将它们全部导入:

File "/Users/james/Documents/UtilityCRM-Server/crm/leads/urls.py", line 2, in <module>
    from leads import views
  File "/Users/james/Documents/UtilityCRM-Server/crm/leads/views.py", line 11, in <module>
    from leads.serializers import LeadSerializer
  File "/Users/james/Documents/UtilityCRM-Server/crm/leads/serializers.py", line 4, in <module>
    from notes.serializers import NoteSerializer
  File "/Users/james/Documents/UtilityCRM-Server/crm/notes/serializers.py", line 6, in <module>
    from leads.serializers import LeadSerializer
ImportError: cannot import name LeadSerializer

非常感谢任何帮助!

代码

这是我设置文件的已安装应用部分:

from leads.serializers import LeadSerializer
from notes.serializers import NotesSerializer
from callbacks.serializers import CallbackSerializer

注意到/ models.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # 3rd Party Apps
    'rest_framework',
    'generic_relations',
    # My Apps
    'leads.apps.LeadsConfig',
    'callbacks.apps.CallbacksConfig',
    'notes.apps.NotesConfig',
]

导致/ models.py

from __future__ import unicode_literals

from django.db import models
from django.utils import timezone
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType

class Note(models.Model):
    author = models.ForeignKey('auth.User')
    title = models.CharField(max_length=100)
    text = models.TextField()
    created_date = models.DateTimeField(default=timezone.now)

    # Relations
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    note_object = GenericForeignKey('content_type', 'object_id')

    def __str__(self):
        return self.title

我有2个序列化器:

导致/ serializers.py

from __future__ import unicode_literals

from django.db import models
from django.contrib.contenttypes.fields import GenericRelation
from django.utils import timezone

from notes.models import Note
from callbacks.models import Callback

GAS = 'G'
ELECTRICITY = 'E'
LEAD_TYPE_CHOICES = (
    (GAS, 'Gas'),
    (ELECTRICITY, 'Electricity'),
)

# Create your models here.
class Lead(models.Model):

    author = models.ForeignKey('auth.User')
    type = models.CharField(
        max_length=1,
        choices=LEAD_TYPE_CHOICES,
        default=GAS,
    )
    business_registration_number = models.IntegerField(max_length=20)
    business_name = models.CharField(max_length=50)
    mpan = models.IntegerField(max_length=21)
    supplier = models.CharField(max_length=45)
    contract_length = models.IntegerField(max_length=2)
    contract_start_date = models.DateField()
    contract_end_date = models.DateField()
    address_line_1 = models.CharField(max_length=45)
    address_line_2 = models.CharField(max_length=45)
    address_line_3 = models.CharField(max_length=45)
    address_city = models.CharField(max_length=45)
    address_county = models.CharField(max_length=45)
    address_postcode = models.CharField(max_length=10)
    contact_title = models.CharField(max_length=45)
    contact_first_name = models.CharField(max_length=45)
    contact_middle_name = models.CharField(max_length=45)
    contact_last_name = models.CharField(max_length=45)
    contact_telephone = models.IntegerField(max_length=11)
    contact_email = models.EmailField(max_length=60)
    created_date = models.DateTimeField(default=timezone.now)

    # Relations
    assigned_to = models.ForeignKey('auth.User', related_name='+')
    #from_batch = models.ForeignKey('data_batch.DataBatch', related_name='+')
    #callbacks = GenericRelation(Callback)
    notes = GenericRelation(Note)

    class Meta:
        ordering = ('contract_end_date', 'business_name',)

    def __str__(self):
        return self.business_name

注意到/ serializers.py

from rest_framework import serializers
from leads.models import Lead, LEAD_TYPE_CHOICES

from notes.serializers import NoteSerializer

class LeadSerializer(serializers.ModelSerializer):
    notes = NoteSerializer(many=True, read_only=True)

    class Meta:
        model = Lead
        fields = (
            'id',
            'business_name',
            'business_registration_number',
            'supplier',
            'contract_length',
            'contract_start_date',
            'notes'
            )

3 个答案:

答案 0 :(得分:2)

有一个想法在我也遇到同样的错误之前解决这个问题我会向你解释我是如何解决的。

将您的应用置于项目目录

project
  -project
    -appname1
      -models.py
      -serilizer.py
    -appname2
     -models.py
     -serilizer.py
   -settings.py
在settings.py

INSTALLED_APPS = ['project.appname1', 'project.appname2']

然后尝试将appname1序列化程序导入appname2

像这样

from project.appname1.serializers import( ArtistSerializer, ArtisTokenSerilizer, ProfessionSerilizer, FollowersSerializer,
            FollowingSerializer, ChatMessageSerializer, SendMessageSerializer, ConversationMessageSerializer,
            ProjectTypeSerializer)

答案 1 :(得分:2)

正如我之前在评论中提到的,我认为这是由于Python中的循环(循环)导入而发生的。 特别是当您在模型中声明相关字段时,会发生这种情况,而某些模型尚未实例化。

在这种情况下,当您执行程序时,它会尝试导入 LeadSerializer ,这需要导入 NoteSerializer ,需要导入 LeadSerializer ,这需要导入 NoteSerializer ...看看这是怎么回事?

你的堆栈跟踪说明了一切:

from leads.serializers import LeadSerializer

from notes.serializers import NoteSerializer

from leads.serializers import LeadSerializer

生成 ImportError:无法导入名称LeadSerializer

我为解决这个问题所做的是在单个文件中声明所有序列化程序。因此,您有两种选择:

  1. LeadSerializer 移至notes / serializers.py
  2. NoteSerializer 移至leads / serializers.py
  3. 这不是解决这个问题最优雅的方法,但它已经完成了它的伎俩。

    下面的部分没有提供有关如何解决此问题的进一步说明,而是对此问题的观察。

    也许Django&amp; DRF可以在未来提供避免这种情况的方法,例如将序列化器声明为

    note_object = GenericRelatedField({
        Lead: 'leads.serializers'.LeadSerializer,
        Callback: CallbackSerializer()
    })
    

    notes = 'notes.serializers'.NoteSerializer(many=True, read_only=True)
    

答案 2 :(得分:2)

面对这一点,做了这件事:

notes = serializers.SerializerMethodField()

def get_notes(self, obj):
    from leads.serializers import LeadSerializer
    return LeadSerializer(<your_queryset>, many=True/False, read_only=True/False).data