2017-04-02 24 views
0

我試圖在以下位置實現API:Django Rest - 「<ClientProfile:[email protected]>」需要爲字段「clientprofile」賦值,然後才能使用這種多對多關係

  • 返回所有ClientProfile對象,包含定位對象的列表嵌套多對多場(我真的不關心,如果它是PK還是實際對象,實際對象將是很好的。)
  • 能POST一個ClientProfile對象,並使用Location對象的PK來指定哪些Location對象應該與它關聯,如下所示:

     { 
         "user": { 
          "email": "[email protected]" 
         }, 
         "first_name": "Mike", 
         "last_name": "Tyson", 
         "locations": [ 
          1,5,21 
    
         ] 
        } 
    
  • 我看到有人對普通的Django說「你需要實現一個保存方法」。我是新來的Django Django的和休息,所以不知道在哪裏或如何實現一個解決方案..

請救我脫離這噩夢!

匹凍結輸出:

appdirs==1.4.0 
chardet==2.3.0 
Django==1.10.5 
django-csvimport==2.5 
djangorestframework==3.5.4 
packaging==16.8 
pyparsing==2.1.10 
six==1.10.0 

錯誤:

Traceback (most recent call last): 
    File "/venv/project/userauth/tests/User.py", line 28, in setUp 
    self.response = self.client.post(path="/client-profile/", format="json", data=self.data) 
    File "/venv/lib/python3.5/site-packages/rest_framework/test.py", line 290, in post 
    path, data=data, format=format, content_type=content_type, **extra) 
    File "/venv/lib/python3.5/site-packages/rest_framework/test.py", line 212, in post 
    return self.generic('POST', path, data, content_type, **extra) 
    File "/venv/lib/python3.5/site-packages/django/test/client.py", line 409, in generic 
    return self.request(**r) 
    File "/venv/lib/python3.5/site-packages/rest_framework/test.py", line 279, in request 
    return super(APIClient, self).request(**kwargs) 
    File "/venv/lib/python3.5/site-packages/rest_framework/test.py", line 231, in request 
    request = super(APIRequestFactory, self).request(**kwargs) 
    File "/venv/lib/python3.5/site-packages/django/test/client.py", line 494, in request 
    six.reraise(*exc_info) 
    File "/venv/lib/python3.5/site-packages/django/utils/six.py", line 686, in reraise 
    raise value 
    File "/venv/lib/python3.5/site-packages/django/core/handlers/exception.py", line 39, in inner 
    response = get_response(request) 
    File "/venv/lib/python3.5/site-packages/django/core/handlers/base.py", line 187, in _get_response 
    response = self.process_exception_by_middleware(e, request) 
    File "/venv/lib/python3.5/site-packages/django/core/handlers/base.py", line 185, in _get_response 
    response = wrapped_callback(request, *callback_args, **callback_kwargs) 
    File "/venv/lib/python3.5/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view 
    return view_func(*args, **kwargs) 
    File "/venv/lib/python3.5/site-packages/django/views/generic/base.py", line 68, in view 
    return self.dispatch(request, *args, **kwargs) 
    File "/venv/lib/python3.5/site-packages/rest_framework/views.py", line 483, in dispatch 
    response = self.handle_exception(exc) 
    File "/venv/lib/python3.5/site-packages/rest_framework/views.py", line 443, in handle_exception 
    self.raise_uncaught_exception(exc) 
    File "/venv/lib/python3.5/site-packages/rest_framework/views.py", line 480, in dispatch 
    response = handler(request, *args, **kwargs) 
    File "/venv/project/userauth/views/ClientProfile.py", line 25, in post 
    serializer.save() 
    File "/venv/lib/python3.5/site-packages/rest_framework/serializers.py", line 214, in save 
    self.instance = self.create(validated_data) 
    File "/venv/project/userauth/serializers/ClientProfile.py", line 20, in create 
    client_profile = ClientProfile.objects.create(user=user, **validated_data) 
    File "/venv/lib/python3.5/site-packages/django/db/models/manager.py", line 85, in manager_method 
    return getattr(self.get_queryset(), name)(*args, **kwargs) 
    File "/venv/lib/python3.5/site-packages/django/db/models/query.py", line 397, in create 
    obj = self.model(**kwargs) 
    File "/venv/lib/python3.5/site-packages/django/db/models/base.py", line 550, in __init__ 
    setattr(self, prop, kwargs[prop]) 
    File "/venv/lib/python3.5/site-packages/django/db/models/fields/related_descriptors.py", line 499, in __set__ 
    manager = self.__get__(instance) 
    File "/venv/lib/python3.5/site-packages/django/db/models/fields/related_descriptors.py", line 476, in __get__ 
    return self.related_manager_cls(instance) 
    File "/venv/lib/python3.5/site-packages/django/db/models/fields/related_descriptors.py", line 783, in __init__ 
    (instance, self.source_field_name)) 
ValueError: "<ClientProfile: [email protected]>" needs to have a value for field "clientprofile" before this many-to-many relationship can be used. 

型號:

class ClientProfile(models.Model): 
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='client_profile') 
    enabled = models.BooleanField(_('Enabled?'), default=False) 
    first_name = models.CharField(max_length=50) 
    last_name = models.CharField(max_length=50) 
    locations = models.ManyToManyField(Location, related_name='client_profile') 

    def __str__(self): 
     return self.user.email 


class Location(models.Model): 
    company = models.ForeignKey(Company) 
    display_name = models.CharField(max_length=50, null=True) 
    address1 = models.CharField(max_length=50, null=True) 
    address2 = models.CharField(max_length=50, null=True) 
    city = models.CharField(max_length=50, null=True) 
    county = models.CharField(max_length=50, null=True) 
    postcode = models.CharField(max_length=50, null=True) 
    country = models.CharField(max_length=50, null=True) 
    tel = models.CharField(max_length=50, null=True) 
    email = models.CharField(max_length=50, null=True) 

串行器:

class ClientProfileSerializer(serializers.ModelSerializer): 
    user = UserSerializer(required=True) 
    locations = LocationSerializer(required=False, many=True) 

    class Meta: 
     model = ClientProfile 
     fields = ('id', 'user', 'first_name', 'last_name', 'locations') 

    def create(self, validated_data): 
     user_data = validated_data.pop('user') 
     user = User.objects.create(email=user_data['email'], is_client=True) 
     client_profile = ClientProfile.objects.create(user=user, **validated_data) 

     return client_profile 


class LocationSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Location 
     fields = ('id', 'company', 'display_name', 'address1', 'address2', 
        'city', 'county', 'postcode', 'country', 'tel', 'email') 

瀏覽次數:

class ClientProfileList(APIView): 
    """ 
    List all ClientProfiles, or create a new ClientProfile. 
    """ 
    def get(self, request, format=None): 
     if self.request.user.is_client: 
      client_profiles = ClientProfile.objects.all() 
      serializer = ClientProfileSerializer(client_profiles, many=True) 
      return Response(serializer.data) 
     else: 
      return Response(status=status.HTTP_401_UNAUTHORIZED) 

    def post(self, request, format=None): 
     serializer = ClientProfileSerializer(data=request.data) 
     if serializer.is_valid(): 
      serializer.save() 
      return Response(serializer.data, status=status.HTTP_201_CREATED) 
     return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) 


class ClientProfileDetail(APIView): 
    """ 
    Retrieve, update or delete a ClientProfile instance. 
    """ 
    def get_object(self, pk): 
     try: 
      return ClientProfile.objects.get(pk=pk) 
     except ClientProfile.DoesNotExist: 
      raise Http404 

    def get(self, request, pk, format=None): 
     client_profile = self.get_object(pk) 
     serializer = ClientProfileSerializer(client_profile) 
     return Response(serializer.data) 

    def put(self, request, pk, format=None): 
     client_profile = self.get_object(pk) 
     serializer = ClientProfileSerializer(client_profile, data=request.data) 
     if serializer.is_valid(): 
      serializer.save() 
      return Response(serializer.data) 
     return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) 

    def delete(self, request, pk, format=None): 
     client_profile = self.get_object(pk) 
     client_profile.delete() 
     return Response(status=status.HTTP_204_NO_CONTENT) 
class LocationList(APIView): 
    """ 
    List all Locations, or create a new Location. 
    """ 
    def get(self, request, format=None): 
     if self.request.user.is_authenticated: 
      if self.request.user.is_client: 
       locations = Location.objects.all() 
       serializer = LocationSerializer(locations, many=True) 
       return Response(serializer.data) 
      else: 
       return Response(status=status.HTTP_403_FORBIDDEN) 
     else: 
      return Response(status=status.HTTP_401_UNAUTHORIZED) 

    def post(self, request, format=None): 
     serializer = LocationSerializer(data=request.data) 
     if serializer.is_valid(): 
      serializer.save() 
      return Response(serializer.data, status=status.HTTP_201_CREATED) 
     return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) 

class LocationDetail(APIView): 
    """ 
    Retrieve, update or delete a Location instance. 
    """ 
    def get_object(self, pk): 
     try: 
      return Location.objects.get(pk=pk) 
     except Location.DoesNotExist: 
      raise Http404 

    def get(self, request, pk, format=None): 
     location = self.get_object(pk) 
     serializer = LocationSerializer(location) 
     return Response(serializer.data) 

    def put(self, request, pk, format=None): 
     location = self.get_object(pk) 
     serializer = LocationSerializer(location, data=request.data) 
     if serializer.is_valid(): 
      serializer.save() 
      return Response(serializer.data) 
     return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) 

    def delete(self, request, pk, format=None): 
     location = self.get_object(pk) 
     location.delete() 
     return Response(status=status.HTTP_204_NO_CONTENT) 

回答

0

Django模型與ManyToMany領域必須保存,然後才能添加相關實例。 (要在ManyToMany關係中添加條目,Django需要僅在創建模型後設置的父模型實例pk。)

因此,在添加任何相關的Location實例之前,必須保存您的ClientProfile。

要修正這個錯誤,只是更新ClientProfileSerializer.create方法:

class ClientProfileSerializer(serializers.ModelSerializer): 

    def create(self, validated_data): 
     user_data = validated_data.pop('user') 
     user = User.objects.create(email=user_data['email'], is_client=True) 
     locations = validated_data.pop('locations') 
     client_profile = ClientProfile.objects.create(user=user, **validated_data) 
     client_profile.locations.add(*locations) 
     return client_profile 
相關問題