使用ForeignKey序列化Django模型

时间:2016-11-20 19:07:16

标签: python django django-rest-framework

在Django Rest Framework中,我有一个简单的Present模型,它包含以下字段:

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)

UserPresent模型的序列化器就是这些:

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': 'WESH@wanadoo.fr', '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

修改

保存Present的唯一方法是将blank=True或/和null=True添加到ForeignKey。但是,我希望在保存对象时分配user_id字段,但此字段不会保留在validated_data中。我该如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

您正在将序列化程序字段设置为read_only,这意味着在创建或更新对象时,只有在读取对象时才会使用它。

  

只读字段包含在API输出中,但在创建或更新操作期间不应包含在输入中。任何' read_only'错误地包含在序列化程序输入中的字段将被忽略。将此属性设置为True可确保在序列化表示时使用该字段,但在反序列化期间创建或更新实例时不使用该字段。

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

另外,请尝试使用PrimaryKeyRelatedField代替RelatedField。有关该字段,请参阅documentation