如何使用DRF中的一个请求创建多个对象(相关)? [英] How to create multiple objects (related) with one request in DRF?

查看:303
本文介绍了如何使用DRF中的一个请求创建多个对象(相关)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个代表作业的类,一个代表标签的类,它描述了一个作业,然后我有一个类在它们之间建立一个关系(连接表),所以一个作业可以被多个标签描述:

 类JobTag(models.Model):
job = models.ForeignKey(Job,unique = False,related_name ='jobtags' )
tag = models.ForeignKey(Tag,unique = False,related_name ='Tag_For_Job')

created_time = models.DateTimeField(auto_now_add = True)
modified_time = models.DateTimeField (auto_now = True)

class Meta:
unique_together =('job','tag',)

def __unicode __(self):
返回'Tag'+ self.tag.name +'作业'+ self.job.name

然后我有序列化程序:

  class TagSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model =标签
fields =('url','name' ,'badge_pic')
read_only_fields =('name','badge_pic')

class JobTagSerializer(serializers.HyperlinkedModelSerializer):
tag = TagSerializer()
class Meta:
model = JobTag
fields =('tag',)
depth = 1

类JobSerializer(serializers.HyperlinkedModelSerializer):
jobtags = JobTagSerializer(many = True)
class Meta:
model = Job
fields =('url','name','employer','jobtags','description')
read_only_fields =('雇主')

所以GET请求的http响应是:

  {
url:http://127.0.0.1:8000/api/jobs/2/,
name:Odprac mi sneh,
雇主:http://127.0.0.1:8000/api/users/4/,
jobtags:[
{
tag:{
url:http://127.0.0.1:8000/api/tags/2/ ,
name:Odhadzovanie snehu,
badge_pic:http://127.0.0.1:8000/media/pictures/tags/0005.jpg
}
}
],
description:blablabla
}

我的问题是非常明显的,我如何创建一个工作实例,并使用一个POST http请求来保存相关的JobTag?



我试图重复一遍方法 http://www.django-rest-framework .ORG / API引导/串行器/#写嵌套的表示的。

  class JobSerializer(serializers.HyperlinkedModelSerializer):
jobtags = JobTagSerializer(many = True)
class Meta :
model = Job
fields =('url','name','employer','jobtags','description')
read_only_fields =('雇主')
def create(self,validated_data):
jobtag_data = validated_data.pop('jobtags')
job = Job.objects.create(** validated_data)
JobTag.objects.create(job = job,** jobtag_data)
return job

但是它返回了create()以后**必须是一个映射,没有列出错误,那么请求data json看起来像什么?



或者这种方法不能在我的情况下使用,我应该做一些完全不同的事情?



我会感谢任何帮助。



修改



如果我尝试访问列表:

  def create(self,validated_data):
jobtag_data = validated_data.pop('jobtags')
job = Job。 objects.create(** validated_data)
JobTag.objects.create(job = job,** jobtag_data [0])
返回作业

我发出另一个错误:无法分配OrderedDict():JobTag.tag必须是Tag实例。
所以我猜我的贴子json是错误的格式?我以这种方式尝试了topost数据:

  {
name:Odprac mi sneh,
jobtags:[
{
tag:{
url:http://127.0.0.1:8000/api/tags/2/
}
}
],
description:veela sneu nemam ruky makam makam makamam,
}


解决方案

如果有人面对这个,我想出了最合适的解决方案,以便在对象为创建和嵌套序列化被用作输出是这样的:



我为每种情况编写序列化程序,用于序列化发送到客户端的数据:

  class JobTagNestedSerializer(serializers.HyperlinkedModelSerializer):
tag = TagSerializer()
class Meta:
model = JobTag
fields =('tag',)
深度= 1



类JobNestedSerializer(serializers.HyperlinkedModelSerializer):
jobtags = JobTagNestedSerializer(many = True,read_only = True)
class Meta:
model = Job
fields =('url','name','employer','jobtags','description')
read_only_fields =('雇主')

并创建新作业,因此从客户端发送到DRF的数据:



pre> class JobTagSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = JobTag
fields =('tag',)

类JobCreateSerializer(serializers.HyperlinkedModelSerializer):
jobtags = JobTagSerializer(many = True,required = False)
class Meta:
model = Job
fields = ('url','name','employer','jobtags','description')
read_only_fields =('雇主')

def create(self,validated_data):
tag_data = validated_data.pop('jobtags')
job = Job.objects.create(** validated_data)
在tag_data中的标签:
d = dict(tag)
JobTag.objects.create(job = job,tag_id = d ['tag']。pk)
返回作业
pre>

所以DRF期待客户端的POST json看起来像:

  {
name:Odprac mi sneh,
雇主:http://127.0.0.1:8000/api/users/4/,
jobtags:[
{
tag:http://127.0.0.1:8000/api/tags/2/
},
{
tag:http://127.0.0.1:8000/api/tags/5/
}
],
description:veela sneu nemam ruky makam makam makamam
}


I have one class representing a Job, one class representing a Tag, which describes a Job and then I have a class making a relationship (junction table) between them, so a Job can be described by multiple Tags:

class JobTag(models.Model):
    job = models.ForeignKey(Job, unique=False, related_name='jobtags')
    tag = models.ForeignKey(Tag, unique=False, related_name='Tag_For_Job')

    created_time = models.DateTimeField(auto_now_add = True)
    modified_time = models.DateTimeField(auto_now = True)

    class Meta:
        unique_together = ('job', 'tag',)

    def __unicode__(self):
        return 'Tag '+self.tag.name +' for job '+ self.job.name

Then I have serializers:

class TagSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Tag
        fields = ('url','name','badge_pic')
        read_only_fields = ('name','badge_pic')

class JobTagSerializer(serializers.HyperlinkedModelSerializer):
    tag = TagSerializer()
    class Meta:
        model = JobTag
        fields = ('tag',)
        depth=1

class JobSerializer(serializers.HyperlinkedModelSerializer):
    jobtags=JobTagSerializer(many=True)
    class Meta:
        model = Job
        fields = ('url','name', 'employer','jobtags','description')
        read_only_fields = ('employer',)

So the http response on GET request is:

{
        "url": "http://127.0.0.1:8000/api/jobs/2/",
        "name": "Odprac mi sneh",
        "employer": "http://127.0.0.1:8000/api/users/4/",
        "jobtags": [
            {
                "tag": {
                    "url": "http://127.0.0.1:8000/api/tags/2/",
                    "name": "Odhadzovanie snehu",
                    "badge_pic": "http://127.0.0.1:8000/media/pictures/tags/0005.jpg"
                }
            }
        ],
        "description": "blablabla"
    }

My question is pretty much obvious, how can I create a job instance and persist them with related JobTags with one POST http request?

I tried to repeat this method http://www.django-rest-framework.org/api-guide/serializers/#writable-nested-representations.

class JobSerializer(serializers.HyperlinkedModelSerializer):
        jobtags=JobTagSerializer(many=True)
        class Meta:
            model = Job
            fields = ('url','name', 'employer','jobtags','description')
            read_only_fields = ('employer',)
        def create(self, validated_data):
            jobtag_data = validated_data.pop('jobtags')
            job = Job.objects.create(**validated_data)
            JobTag.objects.create(job=job, **jobtag_data)
            return job

But it returned "create() argument after ** must be a mapping, not list" error, so what should request.data json looks like?

Or this approach cannot be used in my case and should I do something completly different?

I would appreciate any help.

Edit

if i try to access the list:

def create(self, validated_data):
        jobtag_data = validated_data.pop('jobtags')
        job = Job.objects.create(**validated_data)
        JobTag.objects.create(job=job, **jobtag_data[0])
        return job

I gen another error:"Cannot assign "OrderedDict()": "JobTag.tag" must be a "Tag" instance." So im guessing my posted json is in wrong format? I tried topost data this way:

{
        "name": "Odprac mi sneh",
        "jobtags": [
            {
                "tag": {
                    "url": "http://127.0.0.1:8000/api/tags/2/"
                }
            }
        ],
        "description": "veela sneu nemam ruky makam makam makamam",           
    }

解决方案

If anyone else is facing this, the most suitable solution I figured out, so that the hyperlinked serialisation of jobtags was used when object is created and nested serialisation was used as an output is this:

I wrote serializers for each of these cases, for serialisation of data sent to client:

class JobTagNestedSerializer(serializers.HyperlinkedModelSerializer):
    tag = TagSerializer()
    class Meta:
        model = JobTag
        fields = ('tag',)
        depth=1



class JobNestedSerializer(serializers.HyperlinkedModelSerializer):
    jobtags=JobTagNestedSerializer(many=True,read_only=True)
    class Meta:
        model = Job
        fields = ('url','name', 'employer','jobtags','description')
        read_only_fields = ('employer',)

and for creating new Job, so for data sent from client to DRF:

class JobTagSerializer(serializers.HyperlinkedModelSerializer):
        class Meta:
            model = JobTag
            fields = ('tag',)

class JobCreateSerializer(serializers.HyperlinkedModelSerializer):
        jobtags=JobTagSerializer(many=True,required=False)
        class Meta:
            model = Job
            fields = ('url','name', 'employer','jobtags','description')
            read_only_fields = ('employer',)

        def create(self, validated_data):
            tag_data = validated_data.pop('jobtags')
            job = Job.objects.create(**validated_data)
            for tag in tag_data:
                d=dict(tag)
                JobTag.objects.create(job=job, tag_id=d['tag'].pk)
            return job

So DRF is expecting the POST json from client to looks like:

{
        "name": "Odprac mi sneh",
        "employer": "http://127.0.0.1:8000/api/users/4/",
        "jobtags": [
            {
                "tag": "http://127.0.0.1:8000/api/tags/2/"
            },
            {
                "tag": "http://127.0.0.1:8000/api/tags/5/"
            }
        ],
        "description": "veela sneu nemam ruky makam makam makamam"
    }

这篇关于如何使用DRF中的一个请求创建多个对象(相关)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆