基于Django类的视图处理表单并相应调整上下文

2024-06-26 13:55:02 发布

您现在位置:Python中文网/ 问答频道 /正文

一般来说,我对Django和Python都是新手。我目前正在构建一个Django应用程序,并试图坚持基于类的视图

我有一个我想要处理的表单(FormView),意思是获取数据,清理数据并将其存储在数据库中。处理后,我只想再次显示表单(因此没有重定向到另一个成功页面),并在表单上方显示处理结果。我该怎么做?我已经使用get_context_data为结果消息添加了额外的上下文,但无法确定如何以及在何处处理数据,以及如何将数据与更新上下文数据联系起来。任何帮助都将不胜感激

forms.py:

from django import forms

class URLsForm(forms.Form):
    list_of_urls = forms.CharField(label='One URL per line', widget=forms.Textarea)

views.py

from django.views.generic import FormView
from .models import URL
from .forms import URLsForm

class URLBatchCreateView(FormView):
    form_class = URLsForm
    template_name = 'bot/url_batch_create.html'
    success_url = reverse_lazy('url_batch_create')

    def form_valid(self, form):
        return super(URLBatchCreateView, self).form_valid(form)

    def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            context['created_urls'] = 'The result'
            return context

url\u batch\u create.html:

{% extends 'bot/base.html' %}

{% block content %}

{% if created_urls %}
    <div>The following URLs where created:<br>{{ created_urls }}</div>
{% endif %}

<form action="" method ="post">
    {% csrf_token %}
    <table>
        {{ form.as_table }}
    </table>
    <input type="submit" value="Create">
</form>

{% endblock content %}

URL.py:

from django.urls import path
from .views import URLBatchCreateView

urlpatterns = [
    path('url/batchcreate', URLBatchCreateView.as_view(), name='url_batch_create'),
]

Tags: 数据fromimportformurl表单getcreate
1条回答
网友
1楼 · 发布于 2024-06-26 13:55:02

I have played around with get_context_data to add the additional context for the result message

是的,get_context_data有助于将数据传递给模板

but can't figure out how and where to process the data

你也在正确的轨道上。它可以以有效的形式完成

and how to tie it together with updating the context data then.

为此,您需要对存储数据的数据库对象进行引用。您当前的方法将重定向到同一页,而不带任何参数。这是行不通的,因为当浏览器从重定向的URL加载页面时,这是另一个请求,如果您没有对已创建对象的引用,则无法找到已创建的对象

您可能想看看CreateView和UpdateView,它们可能提供一个更优雅的解决方案(https://docs.djangoproject.com/en/3.1/topics/class-based-views/generic-editing/),但我将提供一个如何完成当前方法的示例

您没有指定数据的存储方式,因此我将提供models.py的示例,以便我的其他更改有意义:

from django.db import models

class URLSet(models.Model):
    pass

class URL(models.Model):
    urlset = models.ForeignKey(URLSet, related_name="urls",
                               on_delete=models.CASCADE)
    url = models.URLField()

URLBatchCreateView也可以处理编辑,因此我将其重命名为URLBatchCreateEditView。它应该能够获取对已创建的URLSet对象的引用,即其id。然后我们可以基于此工作:

from django.shortcuts import get_object_or_404
from django.urls import reverse
from django.views.generic import FormView

from .forms import URLsForm
from .models import URL, URLSet


class URLBatchCreateEditView(FormView):
    form_class = URLsForm
    template_name = 'bot/url_batch_create.html'

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.urlset = None

    def get(self, request, *args, urlset_id=None, **kwargs):
        if urlset_id:
            self.urlset = get_object_or_404(URLSet, id=urlset_id)
        return super().get(request, *args, **kwargs)

    def get_initial(self):
        data = super().get_initial()
        if self.urlset:
            data.update({'list_of_urls': '\n'.join(self.get_urls())})
        return data

    def get_urls(self):
        if self.urlset is None:
            return None
        return [x.url for x in self.urlset.urls.all()]

    def form_valid(self, form):
        urls_text = form.cleaned_data['list_of_urls']
        if not self.urlset:
            self.urlset = URLSet.objects.create()
        else:
            self.urlset.urls.all().delete()
        for url in urls_text.splitlines():
            URL.objects.create(url=url, urlset=self.urlset)
        return super().form_valid(form)

    def get_success_url(self):
        return reverse('url_batch_edit', kwargs={'urlset_id': self.urlset.id})

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['created_urls'] = self.get_urls()
        context['urlset'] = self.urlset
        return context

您还需要新的url:

urlpatterns = [
    path('url/batchcreate', URLBatchCreateEditView.as_view(),
         name='url_batch_create'),
    path('url/batchedit/<int:urlset_id>', URLBatchCreateEditView.as_view(),
         name='url_batch_edit'),
]

当按钮处于编辑模式时,可能不应显示“创建”:

{% if urlset %}
    <input type="submit" value="Save changes">
{% else %}
    <input type="submit" value="Create">
{% endif %}

最后,最好在表单中添加验证:

from django import forms
from django.core import validators


def validate_url_lines(value, schemes=('http', 'https')):
    validate_url = validators.URLValidator(schemes=schemes)
    for line in value.splitlines():
        validate_url(line)


class URLsForm(forms.Form):
    list_of_urls = forms.CharField(label='One URL per line',
                                   widget=forms.Textarea,
                                   validators=[validate_url_lines])

相关问题 更多 >