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)