在基于 Django class 的通用视图 CreateView 中设置表单字段

Setting form fields in django class based generic view CreateView

我正在使用 django 的 CreateView 将图像添加到书中。我将图书的 ID 作为 url 中的参数传递给基于 class 的视图。 booklanguage 等表单字段不会在模板上呈现,而是借助图书 ID 获得的。

# views.py
class PictureCreateView(CreateView):
    model = Upload
    fields = "__all__"
    book_id = None

    def get_initial(self):
        initial = super(PictureCreateView, self).get_initial()
        initial = initial.copy()
        self.book_id = self.kwargs['book_id']
        book = Book.objects.get(id=self.book_id)
        initial['book'] = book
        initial['language'] = language
        initial['uploader'] = self.request.user
        return initial

    # set book_id so it used in the template
    def get_context_data(self, **kwargs):
        context = super(PictureCreateView, self).get_context_data(**kwargs)
        context['book_id'] = self.book_id
        return context

    def form_valid(self, form, **kwargs):
        print('Form is valid')
        self.object = form.save()
        files = [serialize(self.object)]
        data = {'files': files}
        response = JSONResponse(data, mimetype=response_mimetype(self.request))
        response['Content-Disposition'] = 'inline; filename=files.json'
        return super(PictureCreateView, self).form_valid(form)

    def form_invalid(self, form):
        print('Form invalid!')
        print(form.errors)
        data = json.dumps(form.errors)
        return HttpResponse(content=data, status=400, content_type='application/json')

# models.py
class Upload(models.Model):
    image = models.ImageField(upload_to=get_upload_path, help_text='Image to process')
    uploader = models.ForeignKey(settings.AUTH_USER_MODEL, models.CASCADE, related_name='uploader')
    language = models.ForeignKey(Language, models.CASCADE)
    book = models.ForeignKey(Book, models.CASCADE)

问题是我收到一条错误消息,指出表单无效,并且字段 uploaderbooklanguage 是必需的。我该如何解决?

initial 数据用于在最初显示表单时显示默认值。当提交的表单数据中缺少这些值时,不会使用它。如果像 bookuploader 这样的字段是从 URL 或 logged-in 用户设置的,那么你应该将它们完全留在表单之外,而不是在初始数据中设置它们.然后,您可以在保存表单之前在 form_valid 方法中设置实例的值。

from django.contrib.auth.mixins import LoginRequiredMixin

class PictureCreateView(LoginRequiredMixin, CreateView):
    model = Upload
    fields = ['other_field1', 'other_field2', ...]  # leave out book, language and uploader

    def form_valid(self, form):
        self.book_id = self.kwargs['book_id']
        book = Book.objects.get(id=self.book_id)
        form.instance.book = book
        form.instance.language = ????
        form.instance.uploader = self.request.user
        return super(

LoginRequiredMixin 确保只有 logged-in 用户可以访问该视图。

您可能希望使用 get_object_or_404 来处理 book_id 引用不存在的书籍的情况。

一想,初始不填模型提交。您需要在 init

中执行此操作
def __init__(self):
    super(PictureCreateView, self).__init__()
    self.fields['book'] = self.initial['book']
    self.fields['uploader'] = self.initial['uploader']
    self.fields['language'] = self.initial['book']

或者,如果您不想设置字段,请确保它们在您的原始模型中是可选的:

class Upload(models.Model):
    uploader = models.ForeignKey('uploader', on_delete=models.CASCADE, null=True, blank=True)
    book = models.ForeignKey('book', on_delete=models.CASCADE, null=True, blank=True)
    language = models.ForeignKey('language', on_delete=models.CASCADE, null=True, blank=True)