【问题标题】:Foreign key setup issue with DJango and PythonDJango 和 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 调用仍然可以完美执行。
  • 如果您可以包含相关代码会更容易。如果您将图像添加到特定房间,那么该房间已经具有特定属性

标签: python django python-2.7 django-models mysql-python


【解决方案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 存在 不是。

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

    您需要检查:

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

    试试这样的模式:

    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访问正确的房间

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-02-01
        • 1970-01-01
        • 2018-02-15
        • 2018-08-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多