__init__() 得到了意外的关键字参数“id”

问题描述 投票:0回答:1

这是我第一次在这里问问题:)我是 Django 的初学者,我已经坚持使用 edit_booking 方法好几天了,我什至不知道我做错了什么...... 我正在制作一个预订系统,我得到了

"TypeError at /edit-booking/6 __init__() got an unexpected keyword argument 'id'"
。我已经尝试了很多方法来编辑准确的预订,但它们只会导致更多错误......

浏览次数:

class EditBooking(DetailView):

    def __init__(self):    
        template_name = 'edit-profile.html'        
        initial = {}

    @login_required
    def edit_booking(request, id):
        booking = get_object_or_404(Booking, id=id)
        if request.method == 'POST':
            form = BookingForm(request.POST, instance=booking)
            customer_data = UserProfile.objects.all()
            if form.is_valid():
                instance = form.save(commit=False)
                instance.customer_data = customer_data
                instance.save()
                messages.success(request, 'Thank you! Your booking has been updated!')
            else:
                return messages.error(request, form.errors)
        else:
            form = BookingForm(initial={
                'booking_date': booking.booking_date,
                'booking_time': booking.booking_time,
                'table_size': booking.table_size,
                'additional_info': booking.additional_info,
            })
        return render(request, template_name, {'form': form})

模板:

profile.html按钮触发编辑页面:

<a href="{% url 'editbooking' id=booking.id %}" aria-label="edit booking">
    <button type="button" class="btn btn-secondary btn-brown px-5">Edit</button>
</a>

edit_booking.html:

<form method="POST" action="{% url 'editbooking' id=booking.id %}" 
class="col-6">                                  
    {% csrf_token %}
    {% crispy form %}
</form>

网址:

path('edit-booking/<int:id>', views.EditBooking, name='editbooking'),

型号:

class Booking(models.Model):

    booking_customer = models.ForeignKey(UserProfile, on_delete=models.CASCADE, null=True)
    booking_date = models.DateField(default=datetime.date.today)
    booking_time = models.CharField(choices=TIME_SLOTS, default='8:00 - 8:30', max_length=50)
    table_size = models.CharField(choices=TABLE_SIZE, default='1', max_length=50)
    additional_info = models.TextField(max_length=400, null=True, blank=True)
    booked_on = models.DateTimeField(auto_now_add=True)
    is_confirmed = models.CharField(choices=CONFIRMATION, default='Awaiting confirmation', max_length=50)
    slug = AutoSlugField(max_length=70, unique=True, null=True)


    class Meta:
        ordering = ["booked_on"]
        

    def __str__(self):

        return f'Booking for {self.booking_date} at {self.booking_time} was booked on {self.booked_on} and currently has a status: {self.is_confirmed}'

表格:

class BookingForm(ModelForm):
    """ 
    Provides necessary fields to the booking form for customers
    """

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

        super().__init__(*args, **kwargs)

        # Crispy form helpers
        self.helper = FormHelper()
        self.helper.form_method = 'post'        
        self.helper.add_input(Submit('submit', 'Submit', css_class='btn btn-secondary btn-brown mb-4 mx-auto px-5'))        

    # Provides a date widget to the form 
    booking_date = forms.DateField(widget=forms.DateInput(attrs={'class':'form-control', 'type':'date', 'value': datetime.date.today}), required=False)
    booking_time = forms.ChoiceField(choices=TIME_SLOTS, required=False)
    table_size = forms.ChoiceField(choices=TABLE_SIZE, required=False)
    additional_info = forms.CharField(max_length=400, widget=SummernoteWidget(), required=False)
    booked_on = forms.DateTimeField(initial=datetime.datetime.now, widget=forms.HiddenInput(), required = False)
    slug = AutoSlugField(max_length=70, unique=True, populate_from=lambda instance: instance.title,
                         unique_with=['booked_on', 'booking_date'],
                         slugify=lambda value: value.replace(' ','-')) 


    # Provides a model to pull the fields from
    class Meta:
        model = Booking
        fields = ['booking_date', 'booking_time', 'table_size', 'additional_info']
        read_only = ['booked_on', 'slug']


    # Prevents booking dates in the past
    def save_booking(self, *args, **kwargs):

        data = self.cleaned_data
        if data.get('booking_date') < datetime.date.today():        
            raise ValidationError("The date cannot be in the past!")
        else:
            super(Booking, self).save(*args, **kwargs)

我试图使用 slug、pk 和 id 来获取准确的预订,我更改了 url 和模板以显示 id,使用 Booking.objects.get() 并最终将其与 get_object_or_404 交换,摆脱了 init 等等...我一直在这里搜索类似的问题,但是我尝试过的解决方案都没有真正对我有用:(

django django-views django-forms
1个回答
0
投票

这里有几个问题。首先,您使用

.as_view()
注册一个基于类的视图,它本质上将类包装到处理请求的函数中,因此:

path('edit-booking/<int:id>', views.EditBooking.as_view(), name='editbooking'),

您现在可能会收到有关

template_name
的错误,并且未指定模型,这是有道理的:您没有定义它,并尝试在构造函数中定义它。您的视图看起来也很像
UpdateView
[Django-doc]
,而不是
DetailView
。您可以将
UpdateView
视为
DetailView
,但具有允许编辑的表单。这还将使用 GET 请求中的实例填充表单,这可能会更方便。

我们可以使用

LoginRequiredMixin
[Django-doc]
SuccessMessageMixin
[Django-doc]
检查用户是否已登录并且在项目成功时也已经编码消息:

没有多大意义的是

.customer_data = customer_data
:您不将其存储在模型对象中。您可以使用登录用户的
.booking_customer
设置
UserProfile
,但这取决于
UserProfile
模型,因此您可能必须修改
form_valid()
方法重载。

最后,成功的 POST 请求通常会导致重定向到某个路径,您可以通过

success_url
:

设置该路径

从 django.contrib.auth.mixins 导入 LoginRequiredMixin 从 django.views.generic 导入 UpdateView

class EditBooking(SuccessMessageMixin, LoginRequiredMixin, UpdateView):
    model = Booking
    form_class = BookingForm
    template_name = 'edit-profile.html'
    success_message = 'Thank you! Your booking has been updated!'
    success_url = '/path/to/some/view'

    # no __init__

    def form_valid(self, form):
        form.instance.booking_customer = UserProfile.objects.get(
            user=self.request.user
        )
        return super().form_valid(form)
© www.soinside.com 2019 - 2024. All rights reserved.