Django 模型表单外键字段到持续时间字段不工作

Django 模型表单外键字段到持续时间字段不工作,django,Django,我有以下表单,其中用户选择一个值,该值对应于名为duration的模型中name值的duration字段 当表单提交时,我收到了这个错误 return (24 * 60 * 60 * delta.days + delta.seconds) * 1000000 + delta.microseconds Attribute Error - 'str' object has no attribute days. 显然,Django在调用此方法时希望参数是timedelta对象,而不是获取字符串。我

我有以下表单,其中用户选择一个值,该值对应于名为duration的模型中name值的duration字段

当表单提交时,我收到了这个错误

return (24 * 60 * 60 * delta.days + delta.seconds) * 1000000 + delta.microseconds

Attribute Error - 'str' object has no attribute days.
显然,Django在调用此方法时希望参数是timedelta对象,而不是获取字符串。我错在哪里

表格:

class AuctionCreateForm(forms.ModelForm):

    class Meta:
        model = Auction
        fields = ['title', 'reserve']
        exclude = ('duration',)
        labels = {'reserve': _('Reserve')}

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["duration_value"] = forms.ModelChoiceField(
            queryset=Duration.objects.all(),
            empty_label=None,
            to_field_name="value",
        )    

观点:

class AuctionCreate(CreateView):
    """ View function for creating an auction """
    form_class = AuctionCreateForm
    template_name = "auction/auction_form.html"

    def form_valid(self, form):
        form.instance.start = timezone.now()
        duration_value = form.cleaned_data.get('duration_value')
        form.instance.duration = Duration.objects.get(value=duration_value)
        form.instance.creator = self.request.user
        return super().form_valid(form)
如果有帮助的话,这里有两个模型

class Auction(models.Model):
    """ Model for an auction """
    uuid = models.UUIDField(
        db_index=True,
        default=uuid.uuid4,
        editable=False,
    )
    title = models.CharField(max_length=10)
    valid_from = models.DateTimeField(auto_now_add=True)
    duration = models.ForeignKey(
        Duration, 
        on_delete=models.SET_NULL, 
        null=True
    )
    reserve = models.PositiveIntegerField(default=0)
    creator = models.ForeignKey(
        get_user_model(),
        on_delete=models.SET_NULL,
        null=True,
    )
    winning_bid = models.ForeignKey(
        'Bid',
        related_name='highest_bid',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
    )    


class Duration(models.Model):
    """ Choice durations for auction """
    value = models.DurationField()

    def __str__(self):
        return humanfriendly.format_timespan(self.value)

我知道我拥有的持续时间对象没有问题。我通过管理界面成功地创建了它们,其中提供了一个文本字段,并以秒为单位输入了一个值。此外,在应用程序的另一部分中,我列出了拍卖,我可以检索这些值并对它们进行算术运算

完全回溯-


[22/Apr/2019 13:08:54] "GET /auction/create/ HTTP/1.1" 200 3234
Internal Server Error: /auction/create/
Traceback (most recent call last):
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/core/handlers/base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/core/handlers/base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/views/generic/base.py", line 71, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/views/generic/base.py", line 97, in dispatch
    return handler(request, *args, **kwargs)
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/views/generic/edit.py", line 172, in post
    return super().post(request, *args, **kwargs)
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/views/generic/edit.py", line 141, in post
    if form.is_valid():
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/forms/forms.py", line 185, in is_valid
    return self.is_bound and not self.errors
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/forms/forms.py", line 180, in errors
    self.full_clean()
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/forms/forms.py", line 381, in full_clean
    self._clean_fields()
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/forms/forms.py", line 399, in _clean_fields
    value = field.clean(value)
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/forms/fields.py", line 148, in clean
    value = self.to_python(value)
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/forms/models.py", line 1248, in to_python
    value = self.queryset.get(**{key: value})
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/db/models/query.py", line 402, in get
    num = len(clone)
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/db/models/query.py", line 256, in __len__
    self._fetch_all()
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/db/models/query.py", line 1242, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/db/models/query.py", line 55, in __iter__
    results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1084, in execute_sql
    sql, params = self.as_sql()
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 486, in as_sql
    where, w_params = self.compile(self.where) if self.where is not None else ("", [])
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 402, in compile
    sql, params = node.as_sql(self, self.connection)
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/db/models/sql/where.py", line 81, in as_sql
    sql, params = compiler.compile(child)
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 402, in compile
    sql, params = node.as_sql(self, self.connection)
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/db/models/lookups.py", line 163, in as_sql
    rhs_sql, rhs_params = self.process_rhs(compiler, connection)
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/db/models/lookups.py", line 260, in process_rhs
    return super().process_rhs(compiler, connection)
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/db/models/lookups.py", line 95, in process_rhs
    return self.get_db_prep_lookup(value, connection)
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/db/models/lookups.py", line 187, in get_db_prep_lookup
    [get_db_prep_value(value, connection, prepared=True)]
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/db/models/fields/__init__.py", line 1619, in get_db_prep_value
    return duration_microseconds(value)
  File "/home/ross/.local/share/virtualenvs/v4-MIvAvlKB/lib/python3.6/site-packages/django/utils/duration.py", line 44, in duration_microseconds
    return (24 * 60 * 60 * delta.days + delta.seconds) * 1000000 + delta.microseconds 
这是select小部件的html的外观-

<select name="duration_value" id="id_duration_value">
  <option value="0:05:00">5 minutes</option>

  <option value="0:10:00">10 minutes</option>

  <option value="0:20:00">20 minutes</option>

  <option value="0:40:00">40 minutes</option>

  <option value="1:00:00">1 hour</option>

  <option value="2:00:00">2 hours</option>

  <option value="4:00:00">4 hours</option>

  <option value="8:00:00">8 hours</option>

  <option value="16:00:00">16 hours</option>

  <option value="1 day, 0:00:00">1 day</option>

</select>

5分钟
10分钟
20分钟
40分钟
1小时
2小时
4小时
8小时
16小时
一天

因此,问题是
DurationField
timedelta
对象上工作。因此,您需要将字符串转换为
timedelta
对象,然后执行查找

# views.py
from django.utils.dateparse import parse_duration
class AuctionCreate(CreateView):
    """ View function for creating an auction """
    form_class = AuctionCreateForm
    template_name = "auction/auction_form.html"

    def form_valid(self, form):
        form.instance.start = timezone.now()
        duration_value = form.cleaned_data.get('duration_value')
        duration_obj = parse_duration(duration_value)  # convert string to timedelta object
        form.instance.duration = Duration.objects.get(value=duration_obj)
        form.instance.creator = self.request.user
        return super().form_valid(form)


如果它能帮助任何人

函数的工作方式是这样的-

@login_required
def AuctionCreate(request):
    if request.method == 'POST':
        request.POST = request.POST.copy()
        duration_value = request.POST["duration_value"]
        duration_value = parse_duration(duration_value)
        request.POST["duration_value"] = duration_value
        print(request.POST)
        form = AuctionCreateForm(request.POST)
        if form.is_valid():
            Auction.objects.create(
                title=form.cleaned_data["title"],
                valid_from=timezone.now(),
                duration=Duration.objects.get(value=duration_value),
                reserve=form.cleaned_data["reserve"],
                creator=request.user,
                winning_bid=None
            )
            return HttpResponse("Created auction")
        else:
            return HttpResponse("Something went wrong")
    else:
        form = AuctionCreateForm()
        return render (
            request,
            'auction/auction_form.html',
            {
                'form': form
            }
        )

类似于基于类的视图-

    """ View function for creating an auction """
    form_class = AuctionCreateForm
    template_name = "auction/auction_form.html"    

    def post(self, request, *args, **kwargs):
        request.POST = request.POST.copy()
        duration_value = request.POST["duration_value"]
        duration_value = parse_duration(duration_value)
        request.POST["duration_value"] = duration_value
        return super().post(request, *args, **kwargs)                                                    

    def form_valid(self, form):
        form.instance.start = timezone.now()
        duration_value = form.cleaned_data.get('duration_value')
        form.instance.duration = duration_value
        form.instance.creator = self.request.user
        return super().form_valid(form)


你能分享整个回溯吗?
delta
的定义是什么?我将更新问题,以了解它从数据库中提取的选择选项。如问题中所述,它们都是通过管理界面中的文本输入字段创建的-我为每个字段输入了一个整数秒值。这不起作用,因为问题发生在表单声明有效之前。我尝试过用您建议的方法覆盖post方法并将字段更改为timedelta对象,但显然您无法更改post dict,因为它是不可变的。此外,所有这些当然都是不必要的。Django应该已经注意到这一点并进行转换。