djanga rest框架:'str'对象没有属性'pk'

时间:2019-03-20 18:24:19

标签: django django-rest-framework attributeerror

我正在使用Django Rest Framework。我有一个现有的数据库(无法对其进行任何更改)。我的桌子TestSuite上有复合pk。当我在test_suites上执行get()时,将引发错误-'str' object has no attribute 'pk'。我没有在模型中定义pk,就像使用django一样,我无法定义复合主键。因此,django使用“ id”作为模型的自动生成的pk。我无法在数据库中添加ID(因为无法修改数据库)。 post()可以正常工作,但是get()通过postman()和可浏览的API引发错误。

我是DRF的新手。任何帮助表示赞赏。

数据库创建语句:

CREATE TABLE `test_suite` (
  `team_name` varchar(30) NOT NULL,
  `suite_name` varchar(100) NOT NULL,
  `description` varchar(200) DEFAULT NULL,
  `schedule` varchar(100) DEFAULT NULL,
  `email_list_ok` varchar(200) DEFAULT NULL,
  `email_list_fail` varchar(200) DEFAULT NULL,
  `template_name` varchar(100) NOT NULL,
  PRIMARY KEY (`team_name`,`suite_name`),
  KEY `fk_test_suite__email_templates` (`template_name`),
  CONSTRAINT `fk_test_suite__email_templates` FOREIGN KEY (`template_name`) REFERENCES `email_templates` (`template_name`),
  CONSTRAINT `fk_test_suite__team` FOREIGN KEY (`team_name`) REFERENCES `team` (`team_name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

我需要对此表进行get()和post()操作。下面是我的模型,序列化器和视图集。

models.py

class Team(models.Model):
    team_name = models.CharField(primary_key=True, max_length=30)
    description = models.CharField(max_length=100, blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'team'

class TestSuite(models.Model):
    team_name = models.ForeignKey(Team, on_delete=models.DO_NOTHING, db_column='team_name')
    suite_name = models.CharField(max_length=100)
    description = models.CharField(max_length=200, blank=True, null=True)
    schedule = models.CharField(max_length=100, blank=True, null=True)
    email_list_ok = models.CharField(max_length=200, blank=True, null=True)
    email_list_fail = models.CharField(max_length=200, blank=True, null=True)
    template_name = models.ForeignKey(EmailTemplates, on_delete=models.DO_NOTHING, db_column='template_name')

    class Meta:
        managed = False
        db_table = 'test_suite'
        unique_together = (('team_name', 'suite_name'),)

views.py

class TestSuiteViewSet(viewsets.ModelViewSet):
    queryset = models.TestSuite.objects.values('team_name','suite_name', 'description','schedule','email_list_ok','email_list_fail','template_name')
    serializer_class = serializers.TestSuiteSerializer

class TeamViewSet(viewsets.ModelViewSet):
    queryset = models.Team.objects.all()
    serializer_class = serializers.TeamSerializer

serializers.py

class TestSuiteSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.TestSuite
        fields = ['team_name','suite_name', 'description','schedule','email_list_ok','email_list_fail','template_name']

错误回溯:

File "/usr/local/lib/python3.6/dist-packages/django/core/handlers/exception.py" in inner
  35.             response = get_response(request)

File "/usr/local/lib/python3.6/dist-packages/django/core/handlers/base.py" in _get_response
  128.                 response = self.process_exception_by_middleware(e, request)

File "/usr/local/lib/python3.6/dist-packages/django/core/handlers/base.py" in _get_response
  126.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/usr/lib/python3.6/contextlib.py" in inner
  52.                 return func(*args, **kwds)

File "/usr/local/lib/python3.6/dist-packages/django/views/decorators/csrf.py" in wrapped_view
  54.         return view_func(*args, **kwargs)

File "/usr/local/lib/python3.6/dist-packages/rest_framework/viewsets.py" in view
  116.             return self.dispatch(request, *args, **kwargs)

File "/usr/local/lib/python3.6/dist-packages/rest_framework/views.py" in dispatch
  495.             response = self.handle_exception(exc)

File "/usr/local/lib/python3.6/dist-packages/rest_framework/views.py" in handle_exception
  455.             self.raise_uncaught_exception(exc)

File "/usr/local/lib/python3.6/dist-packages/rest_framework/views.py" in dispatch
  492.             response = handler(request, *args, **kwargs)

File "/usr/local/lib/python3.6/dist-packages/rest_framework/mixins.py" in list
  48.         return Response(serializer.data)

File "/usr/local/lib/python3.6/dist-packages/rest_framework/serializers.py" in data
  768.         ret = super(ListSerializer, self).data

File "/usr/local/lib/python3.6/dist-packages/rest_framework/serializers.py" in data
  262.                 self._data = self.to_representation(self.instance)

File "/usr/local/lib/python3.6/dist-packages/rest_framework/serializers.py" in to_representation
  686.             self.child.to_representation(item) for item in iterable

File "/usr/local/lib/python3.6/dist-packages/rest_framework/serializers.py" in <listcomp>
  686.             self.child.to_representation(item) for item in iterable

File "/usr/local/lib/python3.6/dist-packages/rest_framework/serializers.py" in to_representation
  530.                 ret[field.field_name] = field.to_representation(attribute)

File "/usr/local/lib/python3.6/dist-packages/rest_framework/relations.py" in to_representation
  272.         return value.pk

Exception Type: AttributeError at /dqf_api/test_suites/
Exception Value: 'str' object has no attribute 'pk'

urls.py

router = routers.DefaultRouter()
router.register(r'teams', views.TeamViewSet)
router.register(r'test_suites', views.TestSuiteViewSet)
urlpatterns = [ url(r'^dqf_api/', include(router.urls))]

编辑:

我可以通过将以下代码添加到serializers.py中来解析get()。但是,现在我的post()无法正常工作-ValueError at /dqf_api/test_suites/ Cannot assign "'ede'": "TestSuiteModel.team_name" must be a "Team" instance.

def to_representation(self, obj):
    return {
        'team_name': obj.get('team_name'),
        'suite_name': obj.get('suite_name'),
        'description': obj.get('description'),
        'schedule': obj.get('schedule'),
        'email_list_ok': obj.get('email_list_ok'),
        'email_list_fail': obj.get('email_list_fail'),
        'template_name': obj.get('template_name'),
    }
def to_internal_value(self, data):
        return {
            'team_name': data.get('team_name'),
            'suite_name': data.get('suite_name'),
            'description': data.get('description'),
            'schedule': data.get('schedule'),
            'email_list_ok': data.get('email_list_ok'),
            'email_list_fail': data.get('email_list_fail'),
            'template_name': data.get('template_name'),
        }

错误回溯:

File "/usr/local/lib/python3.6/dist-packages/django/core/handlers/exception.py" in inner
  35.             response = get_response(request)

File "/usr/local/lib/python3.6/dist-packages/django/core/handlers/base.py" in _get_response
  128.                 response = self.process_exception_by_middleware(e, request)

File "/usr/local/lib/python3.6/dist-packages/django/core/handlers/base.py" in _get_response
  126.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/usr/lib/python3.6/contextlib.py" in inner
  52.                 return func(*args, **kwds)

File "/usr/local/lib/python3.6/dist-packages/django/views/decorators/csrf.py" in wrapped_view
  54.         return view_func(*args, **kwargs)

File "/usr/local/lib/python3.6/dist-packages/rest_framework/viewsets.py" in view
  116.             return self.dispatch(request, *args, **kwargs)

File "/usr/local/lib/python3.6/dist-packages/rest_framework/views.py" in dispatch
  495.             response = self.handle_exception(exc)

File "/usr/local/lib/python3.6/dist-packages/rest_framework/views.py" in handle_exception
  455.             self.raise_uncaught_exception(exc)

File "/usr/local/lib/python3.6/dist-packages/rest_framework/views.py" in dispatch
  492.             response = handler(request, *args, **kwargs)

File "/usr/local/lib/python3.6/dist-packages/rest_framework/mixins.py" in create
  21.         self.perform_create(serializer)

File "/usr/local/lib/python3.6/dist-packages/rest_framework/mixins.py" in perform_create
  26.         serializer.save()

File "/usr/local/lib/python3.6/dist-packages/rest_framework/serializers.py" in save
  214.             self.instance = self.create(validated_data)

File "/usr/local/lib/python3.6/dist-packages/rest_framework/serializers.py" in create
  943.             instance = ModelClass._default_manager.create(**validated_data)

File "/usr/local/lib/python3.6/dist-packages/django/db/models/manager.py" in manager_method
  82.                 return getattr(self.get_queryset(), name)(*args, **kwargs)

File "/usr/local/lib/python3.6/dist-packages/django/db/models/query.py" in create
  415.         obj = self.model(**kwargs)

File "/usr/local/lib/python3.6/dist-packages/django/db/models/base.py" in __init__
  477.                     _setattr(self, field.name, rel_obj)

File "/usr/local/lib/python3.6/dist-packages/django/db/models/fields/related_descriptors.py" in __set__
  197.                     self.field.remote_field.model._meta.object_name,

Exception Type: ValueError at /dqf_api/test_suites/
Exception Value: Cannot assign "'ede'": "TestSuiteModel.team_name" must be a "Team" instance.

2 个答案:

答案 0 :(得分:1)

如下更改您的 ref = Database.database().reference() ref.child("locations").observeSingleEvent(of: .value) { (snapshot) in if snapshot.exists() { if let location = snapshot.value as? [String:Any] { for eachLocation in location { print("Location: \(eachLocation)") if let locationCoordinate = eachLocation.value as? [String: Any] { if let lavLatitude = locationCoordinate["latitude"] as? Double { if let lavLongitude = locationCoordinate["longitude"] as? Double { print(lavLatitude) print(lavLongitude) let marker = GMSMarker() marker.position = CLLocationCoordinate2DMake(lavLatitude, lavLongitude) marker.map = mapView } } } } } } } 类,

TestSuiteViewSet



来自Django Doc

  

class TestSuiteViewSet(viewsets.ModelViewSet): queryset = models.TestSuite.objects.all() serializer_class = serializers.TestSuiteSerializer 返回一个values(),该字典在用作迭代时会返回字典,而不是模型实例,是

答案 1 :(得分:0)

存在与外键关系进行序列化和反序列化的问题。我通过将以下代码添加到serializers.py

来修复它
class TestSuiteSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.TestSuiteModel
        fields = ['team_name','suite_name', 'description','schedule','email_list_ok','email_list_fail','template_name']

    def to_representation(self, obj):
        if isinstance(obj, dict): # get methods
            return obj
        else:
            self.fields['team_name'] = TeamSerializer()
            self.fields['template_name'] = EmailTemplatesSerializer()
            return super(TestSuiteSerializer, self).to_representation(obj)