首页 > 解决方案 > Django:两个模型之间的两种关系

问题描述

我正在努力创建两个具有两种关系的模型。

我的目标是一个人可以拥有多个对象,并且始终拥有一个最喜欢的对象(他们拥有)。

因此,准确地说,约束可以总结如下:

class Person(models.Model):
    favorite_object = models.ForeignKey('Object')


class Object(models.Model):
    owner = models.ForeignKey(Person)

首先,我收到一个错误,指出我应该添加一个related_name来帮助解决反向引用,我想知道这里最好的做法是什么,因为从对象的角度来看,最喜欢的关系是可选的。

我是否将所有者更改为

    owner = models.ForeignKey(Person, related_name="+")

首先要避免反向引用?但是,如何查询所有者的所有对象?我什至可以强制要求最喜欢的对象必须由 Django 模型拥有吗?


其次,我首先如何创建对象?他们相互依赖。

如果没有最喜欢的对象,我无法创建用户,也无法在不知道其所有者的情况下创建对象。请注意,在我的情况下,这是一个必要的约束。

我会做这样的事情,但它似乎不起作用

with transaction.atomic():
    my_person = Person()
    my_object = Object(owner=my_person)
    my_person.favorite_object = my_object
    my_person.save()
    my_object.save()

例如,我可以允许Object.owner为 NULL,但这会放松我对每个对象都需要拥有所有者的一般约束。

编辑:

它似乎

    favorite_object = models.ForeignKey('Object', related_name="+")

而不是排除反向关系可能是一个好主意,因为从对象引用回所有者似乎没有必要。首先,无论如何我都可以通过所有者属性检查所有者(我的约束是喜欢一个对象的人也是他们的所有者)。其次,这种反向关系并不总是存在。

标签: djangodjango-rest-framework

解决方案


也许您可以在数据库中有一个“虚拟”对象,这样 Person() 对象就有一个 favorite_object 并且不会创建失败,然后在您创建人的同一视图中,使用该人创建一个对象(这将是人们最喜欢的对象)并更新 Person() 以使用您刚刚创建的对象而不是虚拟对象。

我认为它看起来像这样:

@api_view(['POST'])
@permission_classes((AllowAny,))
def api_user_registration_view(request):
    if request.method == 'POST':
        dummy_object = Object.objects.get(name='dummy')
        person_serializer = PersonRegistrationSerializer(favorite_object=dummy_object, data=request.data)
        data = {

        }
        if person_serializer.is_valid():
            person = person_serializer.save()
            object_serializer = ObjectRegistrationSerializer(owner=person)
            if object_serializer.is_valid():
                object_serializer.save()
            else:
                data = serializer.errors
        else:
            data = serializer.errors
        return Response(data)

在 serializers.py 中,您只需为每个模型声明注册序列化程序

class PersonRegistrationSerializer(serializers.ModelSerializer):
    class Meta:
        model = Person
        fields = '__all__'

class ObjectRegistrationSerializer(serializers.ModelSerializer):
    class Meta:
        model = Object
        fields = '__all__'

我希望这有助于或至少为您指明正确的方向。


推荐阅读