Python 2个以上型号的Tastype关系字段

Python 2个以上型号的Tastype关系字段,python,django,python-3.x,tastypie,Python,Django,Python 3.x,Tastypie,我正在学习为Django项目使用tastypie编写API。我在models.py中有以下代码: 我在api.py中有以下代码: 当我发送一个POST请求到http://127.0.0.1:8000/api/v1/auth i、 e: 然后成功创建一个用户和一个UserProfile对象。但我还想在同一端点中创建UserDeviceID对象。我尝试了不同的组合,但无法创建UserDeviceID对象。有人能用一些示例代码详细介绍一下Tastypie关系字段,让我了解关系在Django中是如何工作

我正在学习为Django项目使用tastypie编写API。我在models.py中有以下代码:

我在api.py中有以下代码:

当我发送一个POST请求到http://127.0.0.1:8000/api/v1/auth i、 e:

然后成功创建一个用户和一个UserProfile对象。但我还想在同一端点中创建UserDeviceID对象。我尝试了不同的组合,但无法创建UserDeviceID对象。有人能用一些示例代码详细介绍一下Tastypie关系字段,让我了解关系在Django中是如何工作的吗

例如,我在api.py中编辑了我的CreateUserProfileResource,并添加了以下行:

    deviceid = fields.ForeignKey('users.api.CreateUserDeviceIdsResource', 'deviceid', full=True)
因此CreateUserProfileResource现在看起来像:

class CreateUserProfileResource(ModelResource):
    user = fields.ForeignKey('users.api.CreateUserResource', 'user', full=True)
    deviceid = fields.ForeignKey('users.api.CreateUserDeviceIdsResource', 'deviceid', full=True)
    class Meta:
        list_allowed_methods = ['get','post']
        ...
        ...
并为UserDeviceID模型添加了新资源:

当我尝试发送POST请求时:

    curl -X POST -H "Content-Type: application/json" -d '{"user": {"email":"a@b.com","username":"abcdef"}, "referral_code":"abc123", "deviceid": {"device_id": "abc"}}' http://127.0.0.1:8000/api/v1/auth
我得到以下错误回溯:

    {"error_message": "null value in column \"user_id\" violates not-null constraint
    DETAIL:  Failing row contains (2, abc, def, ghi, null).
    ", "traceback": "Traceback (most recent call last):

      File \"/vagrant/venv/lib/python3.4/site-packages/django/db/backends/utils.py\", line 65, in execute
        return self.cursor.execute(sql, params)

    psycopg2.IntegrityError: null value in column \"user_id\" violates not-null constraint
    DETAIL:  Failing row contains (2, abc, def, ghi, null).

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

    Traceback (most recent call last):
      File \"/vagrant/venv/lib/python3.4/site-packages/tastypie/resources.py\", line 201, in wrapper
        response = callback(request, *args, **kwargs)
      File \"/vagrant/venv/lib/python3.4/site-packages/tastypie/resources.py\", line 432, in dispatch_list
        return self.dispatch('list', request, **kwargs)
      File \"/vagrant/venv/lib/python3.4/site-packages/tastypie/resources.py\", line 464, in dispatch
        response = method(request, **kwargs)
      File \"/vagrant/venv/lib/python3.4/site-packages/tastypie/resources.py\", line 1340, in post_list
        updated_bundle = self.obj_create(bundle, **self.remove_api_resource_names(kwargs))
      File \"/vagrant/venv/lib/python3.4/site-packages/tastypie/resources.py\", line 2104, in obj_create
        return self.save(bundle)
      File \"/vagrant/venv/lib/python3.4/site-packages/tastypie/resources.py\", line 2247, in save
        self.save_related(bundle)
      File \"/vagrant/venv/lib/python3.4/site-packages/tastypie/resources.py\", line 2318, in save_related
        related_resource.save(related_bundle)
      File \"/vagrant/venv/lib/python3.4/site-packages/tastypie/resources.py\", line 2250, in save
        bundle.obj.save()
      File \"/vagrant/venv/lib/python3.4/site-packages/django/db/models/base.py\", line 589, in save
        force_update=force_update, update_fields=update_fields)
      File \"/vagrant/venv/lib/python3.4/site-packages/django/db/models/base.py\", line 617, in save_base
        updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
      File \"/vagrant/venv/lib/python3.4/site-packages/django/db/models/base.py\", line 698, in _save_table
        result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
      File \"/vagrant/venv/lib/python3.4/site-packages/django/db/models/base.py\", line 731, in _do_insert
        using=using, raw=raw)
      File \"/vagrant/venv/lib/python3.4/site-packages/django/db/models/manager.py\", line 92, in manager_method
        return getattr(self.get_queryset(), name)(*args, **kwargs)
      File \"/vagrant/venv/lib/python3.4/site-packages/django/db/models/query.py\", line 921, in _insert
        return query.get_compiler(using=using).execute_sql(return_id)
      File \"/vagrant/venv/lib/python3.4/site-packages/django/db/models/sql/compiler.py\", line 920, in execute_sql
        cursor.execute(sql, params)
      File \"/vagrant/venv/lib/python3.4/site-packages/django/db/backends/utils.py\", line 81, in execute
        return super(CursorDebugWrapper, self).execute(sql, params)
      File \"/vagrant/venv/lib/python3.4/site-packages/django/db/backends/utils.py\", line 65, in execute
        return self.cursor.execute(sql, params)
      File \"/vagrant/venv/lib/python3.4/site-packages/django/db/utils.py\", line 94, in __exit__
        six.reraise(dj_exc_type, dj_exc_value, traceback)
      File \"/vagrant/venv/lib/python3.4/site-packages/django/utils/six.py\", line 658, in reraise
        raise value.with_traceback(tb)
      File \"/vagrant/venv/lib/python3.4/site-packages/django/db/backends/utils.py\", line 65, in execute
        return self.cursor.execute(sql, params)
    django.db.utils.IntegrityError: null value in column \"user_id\" violates not-null constraint
    DETAIL:  Failing row contains (2, abc, def, ghi, null).
    "}
我理解这意味着,当它试图保存UserDeviceID对象时,它无法在bundle中找到要放入UserDeviceID模型的ForeignKeyUser字段的数据

有人能解释一下需要做些什么才能使这段代码正常工作吗


谢谢

在当前关系中无法实现它。模型资源是模型的真实反映。例如,您可以创建以下内容:

>>> UserProfile.objects.create(refferal_code='asdfasdf', user=User.objects.create_user(username='asdfasdf'))
或者这个:

>>> UserDeviceIds.objects.create(device_id='adfadf', user=User.objects.create_user(username='asdfasdfas'))
但不是在一个指令中同时使用

RESTAPI很棒,因为它非常适合Django ORM自己的接口

因此,您可以使用子对象创建对象,但不能同时使用其他父对象

您将资源命名为具有功能性目的的创建,这显然表明某些内容不正确。您的资源应仅分配给模型

在我看来,RESTAPI非常适合使用,因为它清晰、易于客户理解、易于规则、快速构建、易于测试。但是feet真的没有很好地与Django签约

如果您必须打破一些RESTful规则,不要试图重新定义现有的功能齐全的资源,这可能会带来很多麻烦。相反,为了实现这一目的,需要对一些自定义的分离端点进行详细描述

我建议创建自定义视图,如端点处理json/xml,无论您支持注册什么。在单独的应用程序中保存它,如果您在将来找到更好的解决方案,您将很容易更换它。我建议这样做是因为:1。在一次通话中创建这三个模型对您来说至关重要,如果互联网中断,它将破坏模型。2.会更快

我怀疑是否有现成的应用程序可以解决这个问题,因为sing up对于每个网站来说都是独一无二的

import json

from django.contrib.auth.models import User
from django.http import (HttpResponse, HttpResponseBadRequest,
                         HttpResponseNotAllowed)
from django.views.decorators.csrf import csrf_exempt


@csrf_exempt
def signup(request):
    """
    Description:
    POST faldksfalskdfjalksdf

    Headers:
    sdfasdf

    Attributes:
    sadljfkasdlfksad

    Responses:
    asdf
    """
    if request.method != 'POST':
        return HttpResponseNotAllowed(permitted_methods=('POST',))
    try:
        data = json.loads(request.body)
    except (AttributeError, ValueError):
        return HttpResponseBadRequest(
            json.dumps({'error': 'JSON format invalid',
                        'success': False}),
            content_type='application/json')


    if data.get('username', None) and data.get('device_id', None) and data.get('country', None):
        # add more validation.
        user = User.objects.create_user(username=data['username'])
        UserProfile.objects.create(refferal_code='asdfasdf', user=user)
        UserDeviceIds.objects.create(device_id='adfadf', user=user)
        return HttpResponse(json.dumps({'success': True}),
                            content_type='application/json')

    else:
        return HttpResponseBadRequest(
            json.dumps({'error': 'username, device_id or country attributes missing.',
                        'success': False}),
            content_type='application/json')

我明白你的意思。如果我为用户模型创建一个资源,然后UserProfile和UserDeviceID将是子对象,那么我应该能够创建这些子模型的对象。。。正当您能否详细说明这种方法的缺点是什么?您可以这样做,并且它可以在一个调用中工作,但是您必须更改模型关系才能更改资源关系。缺点是您使应用程序接口成为数据库体系结构的独裁者。您可能会损失数据库效率,并使其他模型或其他操作过于复杂。
    {"error_message": "null value in column \"user_id\" violates not-null constraint
    DETAIL:  Failing row contains (2, abc, def, ghi, null).
    ", "traceback": "Traceback (most recent call last):

      File \"/vagrant/venv/lib/python3.4/site-packages/django/db/backends/utils.py\", line 65, in execute
        return self.cursor.execute(sql, params)

    psycopg2.IntegrityError: null value in column \"user_id\" violates not-null constraint
    DETAIL:  Failing row contains (2, abc, def, ghi, null).

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

    Traceback (most recent call last):
      File \"/vagrant/venv/lib/python3.4/site-packages/tastypie/resources.py\", line 201, in wrapper
        response = callback(request, *args, **kwargs)
      File \"/vagrant/venv/lib/python3.4/site-packages/tastypie/resources.py\", line 432, in dispatch_list
        return self.dispatch('list', request, **kwargs)
      File \"/vagrant/venv/lib/python3.4/site-packages/tastypie/resources.py\", line 464, in dispatch
        response = method(request, **kwargs)
      File \"/vagrant/venv/lib/python3.4/site-packages/tastypie/resources.py\", line 1340, in post_list
        updated_bundle = self.obj_create(bundle, **self.remove_api_resource_names(kwargs))
      File \"/vagrant/venv/lib/python3.4/site-packages/tastypie/resources.py\", line 2104, in obj_create
        return self.save(bundle)
      File \"/vagrant/venv/lib/python3.4/site-packages/tastypie/resources.py\", line 2247, in save
        self.save_related(bundle)
      File \"/vagrant/venv/lib/python3.4/site-packages/tastypie/resources.py\", line 2318, in save_related
        related_resource.save(related_bundle)
      File \"/vagrant/venv/lib/python3.4/site-packages/tastypie/resources.py\", line 2250, in save
        bundle.obj.save()
      File \"/vagrant/venv/lib/python3.4/site-packages/django/db/models/base.py\", line 589, in save
        force_update=force_update, update_fields=update_fields)
      File \"/vagrant/venv/lib/python3.4/site-packages/django/db/models/base.py\", line 617, in save_base
        updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
      File \"/vagrant/venv/lib/python3.4/site-packages/django/db/models/base.py\", line 698, in _save_table
        result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
      File \"/vagrant/venv/lib/python3.4/site-packages/django/db/models/base.py\", line 731, in _do_insert
        using=using, raw=raw)
      File \"/vagrant/venv/lib/python3.4/site-packages/django/db/models/manager.py\", line 92, in manager_method
        return getattr(self.get_queryset(), name)(*args, **kwargs)
      File \"/vagrant/venv/lib/python3.4/site-packages/django/db/models/query.py\", line 921, in _insert
        return query.get_compiler(using=using).execute_sql(return_id)
      File \"/vagrant/venv/lib/python3.4/site-packages/django/db/models/sql/compiler.py\", line 920, in execute_sql
        cursor.execute(sql, params)
      File \"/vagrant/venv/lib/python3.4/site-packages/django/db/backends/utils.py\", line 81, in execute
        return super(CursorDebugWrapper, self).execute(sql, params)
      File \"/vagrant/venv/lib/python3.4/site-packages/django/db/backends/utils.py\", line 65, in execute
        return self.cursor.execute(sql, params)
      File \"/vagrant/venv/lib/python3.4/site-packages/django/db/utils.py\", line 94, in __exit__
        six.reraise(dj_exc_type, dj_exc_value, traceback)
      File \"/vagrant/venv/lib/python3.4/site-packages/django/utils/six.py\", line 658, in reraise
        raise value.with_traceback(tb)
      File \"/vagrant/venv/lib/python3.4/site-packages/django/db/backends/utils.py\", line 65, in execute
        return self.cursor.execute(sql, params)
    django.db.utils.IntegrityError: null value in column \"user_id\" violates not-null constraint
    DETAIL:  Failing row contains (2, abc, def, ghi, null).
    "}
>>> UserProfile.objects.create(refferal_code='asdfasdf', user=User.objects.create_user(username='asdfasdf'))
>>> UserDeviceIds.objects.create(device_id='adfadf', user=User.objects.create_user(username='asdfasdfas'))
import json

from django.contrib.auth.models import User
from django.http import (HttpResponse, HttpResponseBadRequest,
                         HttpResponseNotAllowed)
from django.views.decorators.csrf import csrf_exempt


@csrf_exempt
def signup(request):
    """
    Description:
    POST faldksfalskdfjalksdf

    Headers:
    sdfasdf

    Attributes:
    sadljfkasdlfksad

    Responses:
    asdf
    """
    if request.method != 'POST':
        return HttpResponseNotAllowed(permitted_methods=('POST',))
    try:
        data = json.loads(request.body)
    except (AttributeError, ValueError):
        return HttpResponseBadRequest(
            json.dumps({'error': 'JSON format invalid',
                        'success': False}),
            content_type='application/json')


    if data.get('username', None) and data.get('device_id', None) and data.get('country', None):
        # add more validation.
        user = User.objects.create_user(username=data['username'])
        UserProfile.objects.create(refferal_code='asdfasdf', user=user)
        UserDeviceIds.objects.create(device_id='adfadf', user=user)
        return HttpResponse(json.dumps({'success': True}),
                            content_type='application/json')

    else:
        return HttpResponseBadRequest(
            json.dumps({'error': 'username, device_id or country attributes missing.',
                        'success': False}),
            content_type='application/json')