模型表格外键字段到持续时间字段不起作用

时间:2019-04-22 12:50:06

标签: django

我采用以下形式,其中用户选择一个与名为“持续时间”的模型中名称值的持续时间字段相对应的值。

提交表单时出现此错误

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 

这是选择小部件的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>

2 个答案:

答案 0 :(得分:0)

因此,问题是DurationFieldtimedelta对象上起作用。因此,您需要将字符串转换为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)

答案 1 :(得分:0)

以防万一...

让它像这样在功能上起作用-

@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)