2016-11-20 4 views
0

В Джанго Rest Framework, у меня есть простой Present модель, которая состоит в следующих областях:сериализовать модель Django с ForeignKey

class Present(models.Model): 
    name = models.CharField(max_length=15) 
    price = models.FloatField() 
    link = models.CharField(max_length=15) 
    isAlreadyBought = models.BooleanField() 
    user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True) 

В сериализаторов для моделей User и Present эти из них:

class UserSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = User 
     fields = ('username', 'password', 'email') 



class PresentSerializer(serializers.ModelSerializer): 

    user_id = serializers.RelatedField(source='User', read_only=True) 

    class Meta: 
     model = Present 
     fields = ('name', 'link', 'price', 'isAlreadyBought', 'user_id') 


    def create(self, validated_data, **kwargs): 
     print(kwargs) 
     print(validated_data) 
     return Present.objects.create(**validated_data) 

Моя цель, из следующего запроса POST сохранить новый Present. Для этого я добавил user_id поле на мою просьбу связать мой Present с данным User:

import requests 

save_present = {'name': 'figurine', 'price': '50.8', 'link': 'fake_link', 'isAlreadyBought': 'True', 'user_id': '22'} 
r = requests.post('http://127.0.0.1:8000/present_list', json=save_present) 

Вот как я пытаюсь, но безуспешно до сих пор, чтобы спасти мой Present:

class PresentList(APIView): 
# add a new present 
def post(self, request, format=None): 

    # get user id: 
    # print(request.data['user_id']) 
    # 
    # user = User.objects.get(id=request.data['user_id']) 

    machin = request.data 
    # machin.pop('user_id', None) 
    # machin['user'] = UserSerializer(user).data 

    print('Machin', machin) 

    serializer = PresentSerializer(data=machin) 

    if serializer.is_valid(): 
     print('SERIALIZER OK') 
     serializer.save() 

    else: 
     print(serializer.errors()) 


    return Response('') 

мне не удается выяснить, лучший Django на основе способ достижения этой цели, так как я получаю эту ошибку:

November 20, 2016 - 19:55:34 
Django version 1.10.3, using settings 'tutorial.settings' 
Starting development server at http://127.0.0.1:8000/ 
Quit the server with CONTROL-C. 
23 
Machin {'name': 'figurine', 'link': 'fake_link', 'isAlreadyBought': 'True', 'price': '50.8', 'user': {'password': 'PASSWORD', 'email': '[email protected]', 'username': 'Florian'}} 
SERIALIZER OK 
Internal Server Error: /present_list 
Traceback (most recent call last): 
    File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute 
    return self.cursor.execute(sql, params) 
    File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/backends/sqlite3/base.py", line 337, in execute 
    return Database.Cursor.execute(self, query, params) 
sqlite3.IntegrityError: NOT NULL constraint failed: blog_present.user_id 

The above exception was the direct cause of the following exception: 

Traceback (most recent call last): 
    File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/core/handlers/exception.py", line 39, in inner 
    response = get_response(request) 
    File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/core/handlers/base.py", line 187, in _get_response 
    response = self.process_exception_by_middleware(e, request) 
    File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/core/handlers/base.py", line 185, in _get_response 
    response = wrapped_callback(request, *callback_args, **callback_kwargs) 
    File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view 
    return view_func(*args, **kwargs) 
    File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/views/generic/base.py", line 68, in view 
    return self.dispatch(request, *args, **kwargs) 
    File "/Users/Florian/anaconda/lib/python3.5/site-packages/rest_framework/views.py", line 477, in dispatch 
    response = self.handle_exception(exc) 
    File "/Users/Florian/anaconda/lib/python3.5/site-packages/rest_framework/views.py", line 437, in handle_exception 
    self.raise_uncaught_exception(exc) 
    File "/Users/Florian/anaconda/lib/python3.5/site-packages/rest_framework/views.py", line 474, in dispatch 
    response = handler(request, *args, **kwargs) 
    File "/Users/Florian/PycharmProjects/Backend/tutorial/blog/views.py", line 54, in post 
    serializer.save() 
    File "/Users/Florian/anaconda/lib/python3.5/site-packages/rest_framework/serializers.py", line 214, in save 
    self.instance = self.create(validated_data) 
    File "/Users/Florian/anaconda/lib/python3.5/site-packages/rest_framework/serializers.py", line 902, in create 
    instance = ModelClass.objects.create(**validated_data) 
    File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/models/manager.py", line 85, in manager_method 
    return getattr(self.get_queryset(), name)(*args, **kwargs) 
    File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/models/query.py", line 399, in create 
    obj.save(force_insert=True, using=self.db) 
    File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/models/base.py", line 796, in save 
    force_update=force_update, update_fields=update_fields) 
    File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/models/base.py", line 824, in save_base 
    updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields) 
    File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/models/base.py", line 908, in _save_table 
    result = self._do_insert(cls._base_manager, using, fields, update_pk, raw) 
    File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/models/base.py", line 947, in _do_insert 
    using=using, raw=raw) 
    File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/models/manager.py", line 85, in manager_method 
    return getattr(self.get_queryset(), name)(*args, **kwargs) 
    File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/models/query.py", line 1045, in _insert 
    return query.get_compiler(using=using).execute_sql(return_id) 
    File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/models/sql/compiler.py", line 1054, in execute_sql 
    cursor.execute(sql, params) 
    File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/backends/utils.py", line 79, in execute 
    return super(CursorDebugWrapper, self).execute(sql, params) 
    File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute 
    return self.cursor.execute(sql, params) 
    File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/utils.py", line 94, in __exit__ 
    six.reraise(dj_exc_type, dj_exc_value, traceback) 
    File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/utils/six.py", line 685, in reraise 
    raise value.with_traceback(tb) 
    File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute 
    return self.cursor.execute(sql, params) 
    File "/Users/Florian/anaconda/lib/python3.5/site-packages/django/db/backends/sqlite3/base.py", line 337, in execute 
    return Database.Cursor.execute(self, query, params) 
django.db.utils.IntegrityError: NOT NULL constraint failed: blog_present.user_id 
[20/Nov/2016 19:55:36] "POST /present_list HTTP/1.1" 500 17246 

EDIT:

Единственный способ сохранить мое Present является добавление blank=True или/и null=True моих ForeignKey. Тем не менее, я хотел бы назначить поле user_id при сохранении моего объекта, но это поле не хранится в validated_data. Как я могу это решить?

+0

Таким образом, сериализатор не проверяет? Что такое сообщение об ошибке? – knbk

+0

Я только что добавил ошибку. – floflo29

+0

Пожалуйста, покажите полный след. – knbk

ответ

1

Вы устанавливаете поле сериализатора на read_only, что означает, что он не будет использоваться при создании или обновлении объекта, только при его чтении.

Read-only fields are included in the API output, but should not be included in the input during create or update operations. Any 'read_only' fields that are incorrectly included in the serializer input will be ignored. Set this to True to ensure that the field is used when serializing a representation, but is not used when creating or updating an instance during deserialization.

http://www.django-rest-framework.org/api-guide/fields/#read_only

Кроме того, попробуйте использовать PrimaryKeyRelatedField вместо RelatedField. См. documentation для поля.

+0

Замена 'RelatedField' на' user_id = serializers.PrimaryKeyRelatedField (read_only = False) 'дает следующую ошибку:' AssertionError: реляционное поле должно содержать аргумент 'queryset', переопределять' get_queryset' или устанавливать read_only = 'True'.' – floflo29

+0

Затем замените 'source = ...' на 'queryset = User.objects.all()' – martinarroyo

+0

С 'queryset = User.objects.all()', я получаю следующую ошибку: 'TypeError: int() аргумент должен быть строкой, байтовым объектом или числом, а не «Пользователь» ' – floflo29