DJango 和 Python 的外键设置问题

Posted

技术标签:

【中文标题】DJango 和 Python 的外键设置问题【英文标题】:Foreign key setup issue with DJango and Python 【发布时间】:2016-05-21 22:05:28 【问题描述】:

我是 DJango 和 Python 的新手。现在我正在构建一个看起来像这样的模型:

属性 -> 房间 -> 图片。

我的意思是说用户可以拥有一个属性。 每个属性都可以有多个房间。 每个房间都可以有多个图像。

现在我在 Room 模型中将属性 ID 设置为外键。

并且 Room ID 作为 Image 模型中的外键。

但是,当我在进行后期调用以插入特定房间和特定属性的新图像时。

即使属性 id 不存在,它也会创建一个图像对象。它只检查房间 ID。

虽然看跌期权执行得很好。

我想在插入新图片之前验证房间 ID 和属性 ID。

代码:

class PropertyRoom(models.Model):
   pass
class PropertyRoom(models.Model):
    property = models.ForeignKey(Property,related_name='rooms')
class PropertyRoomImage(AbstractImage):
    room = models.ForeignKey(PropertyRoom, related_name='images')

【问题讨论】:

能否展示模型的相关部分? @Sayse 我已经添加了基本的模型结构。如果您需要更多说明,请告诉我。 你在属性房间的 fk 不能选择为空,因此每个房间必须有一个属性 是的,确实如此。但问题是,当我为特定房间添加图像时,它只检查房间 ID,我可以传递任何无效的属性 ID,但 post 调用仍然可以完美执行。 如果您可以包含相关代码会更容易。如果您将图像添加到特定房间,那么该房间已经具有特定属性 【参考方案1】:

虽然理论上您的数据库应确保您拥有正确的数据,但在某些情况下可能并非如此,(IIRC 外键可能不会出现在 mysql 上的数据库中,使用混合表引擎(InnoDB 和 MyISAM))

假设您使用表单,您可以在上传表单中添加form validation。

def clean(self):
    cleaned_data = super(MyForm, self).clean()
    image = cleaned_data['image']
    property = cleaned_data['property']
    if image.room.property != property:
        raise ValidationError("room property and supplied property don't match")
    return cleaned_data

您也可以为模型编写相同的逻辑,但请注意默认情况下save 不会调用它们,因此您必须显式创建它们。 Official model validations documentation

image = PropertyRoomImage()
image.room = ...
image.full_clean()   # call it explicitly as save doesn't
image.save()

【讨论】:

【参考方案2】:

localhost:8000/api/properties/221/rooms/1/images 我正在发帖 例如,调用这个 url。房间 id 1 存在,但属性 id 221 存在 不是。

您需要自己实施此检查。模型不知道数据的所有层次结构;或您的业务规则。

您需要检查:

    财产存在 被引用的房间是否属于该属性。 图像类型/尺寸正确;等

试试这样的模式:

from django.http import Http404
from django.shortcuts import get_object_or_404

def api(request, room=None, property=None):
    property = get_object_or_404(Property, pk=property)
    if not property.property_room_set.filter(pk=room).exists():
        raise Http404

    # other checks
    # your normal logic 

【讨论】:

【参考方案3】:

localhost:8000/api/properties/221/rooms/1/images 例如,我正在对这个 url 进行 post call。房间 id 1 存在,但属性 id 221 不存在。

您根本不需要传递房间,或者如果您确实需要,那么您可以忽略它,您可以使用房间的 id 创建一个图像,如果您需要该属性,那么您可以通过room.property访问正确的房间

【讨论】:

以上是关于DJango 和 Python 的外键设置问题的主要内容,如果未能解决你的问题,请参考以下文章

Django REST Framework - 发布包含自然键的外键字段?

通过不同的外键进行循环迭代的 Django 模板

Django过滤与其他模型的外键相关的模型的查询集?

Django的外键创建

如何遍历 Django 字典中的外键?

如何使唯一 = true 的外键在 Django 中成为“可选”?