You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django模型外键验证:限制主人仅能带自有犬只创建遛弯记录

Django模型权限限制:Owner仅关联自有Dog创建GoForAWalk记录

优先推荐使用模型验证器实现,因为它能在模型层面统一拦截非法操作,不管是通过后台管理、表单提交还是代码直接创建对象,都会触发验证,避免出现遗漏。当然也可以在创建对象的业务逻辑中做限制,但仅适用于特定代码路径。

方案一:模型验证器(推荐)

在GoForAWalk模型中添加clean方法,验证关联的dog是否属于当前owner:

from django.core.exceptions import ValidationError
from django.db import models
from django.utils import timezone

class Owner(models.Model):
    name = models.CharField(max_length=30)

class Dog(models.Model):
    name = models.CharField(max_length=30)
    owner = models.ForeignKey(Owner, on_delete=models.CASCADE)

class GoForAWalk(models.Model):
    date = models.DateTimeField(default=timezone.now)
    location = models.CharField(max_length=100)  # 补充max_length参数,避免Django报错
    owner = models.ForeignKey(Owner, on_delete=models.CASCADE)
    dog = models.ForeignKey(Dog, on_delete=models.CASCADE)

    def clean(self):
        super().clean()
        # 验证狗狗归属
        if self.dog.owner != self.owner:
            raise ValidationError("只能为自己的狗狗创建遛弯记录")

    def save(self, *args, **kwargs):
        # 强制调用完整验证(部分场景下clean不会自动触发)
        self.full_clean()
        super().save(*args, **kwargs)

说明

  • clean方法是Django模型的内置验证钩子,会在对象保存前执行;
  • 抛出ValidationError会直接阻止对象保存,并返回错误信息;
  • 补充了location字段的max_length参数,修复原模型的语法问题;
  • 重写save方法调用full_clean(),确保所有场景下验证都生效(比如直接调用save()而不是通过表单)。

方案二:创建对象时的业务逻辑限制

如果只需要在特定业务场景(比如视图)中做限制,可以在创建对象前先校验权限:

from django.http import HttpResponse
from django.utils import timezone
from .models import Owner, Dog, GoForAWalk

def create_walk_record(request):
    # 假设当前登录用户关联到Owner实例
    current_owner = request.user.owner
    dog_id = request.POST.get("dog_id")

    try:
        # 只查询属于当前用户的狗狗
        target_dog = Dog.objects.get(id=dog_id, owner=current_owner)
    except Dog.DoesNotExist:
        return HttpResponse("无权为该狗狗创建记录", status=403)

    # 创建合法的遛弯记录
    GoForAWalk.objects.create(
        date=timezone.now(),
        location="城市中央公园",
        owner=current_owner,
        dog=target_dog
    )
    return HttpResponse("遛弯记录创建成功")

说明

  • 该方式仅在指定的代码路径生效,如果有其他入口(比如admin后台、脚本)创建GoForAWalk对象,可能会绕过限制;
  • 适合业务逻辑单一、所有创建操作都集中在特定视图的场景。

内容的提问来源于stack exchange,提问作者Phil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 01:40:51