【问题标题】:Django custom save method: takes at least 3 arguments (2 given)Django 自定义保存方法:至少需要 3 个参数(给定 2 个)
【发布时间】:2013-12-03 22:07:25
【问题描述】:

我对 Django 中模型的自定义保存方法有疑问。 返回的错误是:

    Traceback (most recent call last):
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/django/core/handlers/base.py", line 114, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/viewsets.py", line 78, in view
    return self.dispatch(request, *args, **kwargs)
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 57, in wrapped_view
    return view_func(*args, **kwargs)
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/views.py", line 399, in dispatch
    response = self.handle_exception(exc)
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/views.py", line 396, in dispatch
    response = handler(request, *args, **kwargs)
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/mixins.py", line 52, in create
    self.object = serializer.save(force_insert=True)
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/serializers.py", line 560, in save
    self.save_object(self.object, **kwargs)
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/serializers.py", line 935, in save_object
    obj.save(**kwargs)
TypeError: save() takes at least 3 arguments (2 given)

这里使用的模型如下。这个想法是一种用于填充用户酒窖(vinibars)的酒瓶的 ERP。 一个瓶子有 4 个外键:1 个用户、1 个酒和两个动作,它们定义了瓶子在哪里以及它是否被评级 (=drunk)

class Wine(models.Model):

    name = models.CharField(max_length=100, blank=True)
    price = models.IntegerField()
    quantity = models.IntegerField()
    description = models.TextField()
    added_on = models.DateTimeField(auto_now_add=True)

class Container(models.Model):

    CONTAINER_TYPE = (
    ('cellar', 'Cellar'),
    ('vinibar', 'Vinibar'),
    ('history', 'History'),
    )

    container_type = models.CharField(max_length=10, choices=CONTAINER_TYPE)
    user = models.ForeignKey(User, related_name='user_id')


class Movement(models.Model):
    date = models.DateTimeField()
    start = models.ForeignKey(Container, related_name='movement_start')
    finish = models.ForeignKey(Container, related_name='movement_finish')
    quantity = models.IntegerField(default=1)

class Bottle(models.Model):
    wine = models.ForeignKey(Wine, null=False)
    user = models.ForeignKey(User, null=False)
    mounted = models.ForeignKey(Movement, related_name='bottle_mounted')
    rated = models.ForeignKey(Movement, null=True, blank=True, default=None, related_name='bottle_rated')
    date_mounted = models.DateTimeField() 
    date_rated = models.DateTimeField(null=True, blank=True, default=None)
    rating = models.IntegerField(validators=[MinValueValidator(0), MaxValueValidator(5)], null=True, blank=True, default=None)
    comment = models.TextField(null=True, blank=True, default=None)

Bottle 的自定义保存方法如下。当我尝试在我的 Django Rest API 中创建一个新瓶子时发生错误

这个save函数的特殊性是创建一个Movement对象,Bottle有一个ForeignKey和save函数的user和wine参数

def save(self, wine, user, force_insert=True, *args, **kwargs):
    d = datetime.now()
    self.wine = wine #wine referencing issue
    self.user = user
    v = Container.objects.get(container_type='vinibar', user=user)
    c = Container.objects.get(container_type='cellar', user=admin) 
    m = Movement(date=d, start=c, finish=v) #quantity=quantity?
    self.mounted = m
    self.date_mounted = d
    super(Bottle, self).save(*args, **kwargs)

我不明白错误指的是哪个参数,我已经尝试了几乎所有我能想到的......

提前感谢您的帮助:)

【问题讨论】:

  • 什么是堆栈跟踪?
  • 调用save的实际代码在哪里
  • @SimeonVisser 我已经添加了堆栈跟踪。 save 方法直接在 Django Rest Framework API 中创建通用 ViewSet 来创建和编辑模型

标签: python django django-rest-framework


【解决方案1】:

您的 save() 方法至少需要三个参数:selfwineuser

def save(self, wine, user, force_insert=True, *args, **kwargs):

这意味着当kwargs 仅包含一个值时,Django REST 框架无法调用save(),如下所示:

obj.save(**kwargs)

您需要将save()的签名改为:

def save(self, *args, **kwargs):

然后您可以从argskwargs 获取wineuser 和其他参数的值(如果它们恰好被Django REST 框架传递)。

【讨论】:

  • 非常感谢您的快速回答。我的问题是需要在保存对象之前创建已安装的运动对象。在什么时候我应该给 super.save() 函数上面计算的参数?
【解决方案2】:

我注意到你的mounted变量在分配给self.mounted时没有定义

self.mounted = mounted

解决这个问题有帮助吗?

【讨论】:

  • 谢谢,它在初始代码中,但我已将其删除以进行测试。它确实需要在那里,但它不能解决问题
猜你喜欢
  • 1970-01-01
  • 2017-06-04
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 2016-05-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多