Tastypie,添加元素到很多关系 [英] Tastypie, add element to a many to many relationship

查看:82
本文介绍了Tastypie,添加元素到很多关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个django tastypie api,并且在 ManyToMany 关系中添加元素有问题



示例,
models.py

  class Picture(models.db):
A人物图片
people = models.ManyToManyField(Person,related_name ='pictures',
help_text =这张照片中的人物,


class Person(models.db):
代表某人的模型
name = models.CharField(max_length = 200,
help_text =这个名字人,

资源:



$ $ $ $ $ $ $ $ $ $ $$$$$$$$$$$$ ,null = True,
related_name =图片,help_text =图片中的人,

class PersonResource(ModelResource):
API资源此人模型
图片= fields.ToManyField(PictureResource,'图片',null = True,
related_name =people,help_text =图片是这个人出现,

我的问题是我想要一个 add_person 我的图片资源的终点。
如果我使用 PUT ,那么我需要指定图片中的所有数据
如果我使用 PATCH ,我仍然需要指定图片中的所有人。
当然我可以简单地生成 / api / picture /:id / add_people URL,我可以处理我的问题。这个问题就是它不会干净。



另一个解决方案是生成 / api / picture /:id / people 终点,我可以做 GET POST PUT ,就像这是一个新的资源,但是我不知道如何实现这个,在这个资源下创建新的用户似乎很奇怪。



任何想法?

解决方案

我通过覆盖API资源的save_m2m函数来实现。以下是使用模型的示例。

  def save_m2m(self,bundle):
for field_name,field_object in self .fields.items():
如果不是getattr(field_object,'is_m2m',False):
继续

如果不是field_object.attribute:
continue

如果field_object.readonly:
继续

#获取经理。
related_mngr = getattr(bundle.obj,field_object.attribute)
#这是从原始函数
#注释掉的代码,它将清除现有的相关Person对象
#if hasattr(related_mngr,'clear'):
#清除它,只是为了安全。
#related_mngr.clear()

related_objs = []

在bundle.data中的related_bundle [field_name]:
#看看这个人是否已经存在于数据库
try:
person = Person.objects.get(name = related_bundle.obj.name)
#如果不存在,那么保存并使用对象TastyPie
#已经准备创建
除了Person.DoesNotExist:
person = related_bundle.obj
person.save()

related_objs.append(person)

related_mngr.add(* related_objs)


I'm building a django tastypie api, and I have a problem with adding elements in ManyToMany relationships

Example, models.py

class Picture(models.db):
    """ A picture of people"""
    people = models.ManyToManyField(Person, related_name='pictures',
        help_text="The people in this picture",
    )

class Person(models.db):
    """ A model to represet a person """
    name = models.CharField(max_length=200,
        help_text="The name of this person",
    )

resources:

class PictureResource(ModelResource):
    """ API Resource for the Picture model """
    people = fields.ToManyField(PersonResource, 'people', null=True,
        related_name="pictures", help_text="The people in this picture",
    )
class PersonResource(ModelResource):
    """ API Resource for the Person model """
    pictures = fields.ToManyField(PictureResource, 'pictures', null=True,
        related_name="people", help_text="The pictures were this person appears",
    )

My problem is that I would like to have an add_person end point in my picture resource. If I use PUT, then I need to specify all the data in the picture If I use PATCH, I still need to specify all the people in the picture. Of course I could simply generate the /api/picture/:id/add_people URL and there I could handle my problem. The problem with that is that it does not feel clean.

Another solution would be to generate the /api/picture/:id/people end point, and there I could do GET, POST, PUT, like it's a new resource, but I don't know how to implement this and it seems strange to create new people under this resource.

Any thoughts?

解决方案

I implemented this by overriding the save_m2m function of the API Resource. Here is an example using your models.

def save_m2m(self, bundle):
    for field_name, field_object in self.fields.items():
        if not getattr(field_object, 'is_m2m', False):
            continue

        if not field_object.attribute:
            continue

        if field_object.readonly:
            continue

        # Get the manager.
        related_mngr = getattr(bundle.obj, field_object.attribute)
            # This is code commented out from the original function
            # that would clear out the existing related "Person" objects
            #if hasattr(related_mngr, 'clear'):
            # Clear it out, just to be safe.
            #related_mngr.clear()

        related_objs = []

        for related_bundle in bundle.data[field_name]:
            # See if this person already exists in the database
            try:
                person = Person.objects.get(name=related_bundle.obj.name)
            # If it doesn't exist, then save and use the object TastyPie
            # has already prepared for creation
            except Person.DoesNotExist:
                person = related_bundle.obj
                person.save()

            related_objs.append(person)

        related_mngr.add(*related_objs)

这篇关于Tastypie,添加元素到很多关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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