获取Django测试的表单数据

huangapple go评论50阅读模式
英文:

Get form-data for Django tests

问题

我想测试一个Django表单,而不必亲自拼写所有通常会进入其中的POST数据。

在一个真实的应用中,这些数据将由浏览器提供,基于Django渲染的表单(作为HTML)。

如何在不通过浏览器的情况下获取这些数据?

form0 = MyForm(instance=obj)  # 在正常使用中显示的表单
data = the_magic_function(form0)  # 如果用户立即按提交键,将被提交的数据

# 可能会操纵数据的某些部分以使测试更有趣

form1 = MyForm(instance=obj, data=data)

# 实际的测试在form1上进行

form.initial 有点像我要找的,但不完全是:它包含Python对象而不是字符串。

英文:

I would like to test a Django form, without spelling out myself all the POSTed data that would normally go into it.

In a real application, this data would be provided by the browser, based on the form as rendered (as HTML) by Django.

How do I get the data without going through the browser?

form0 = MyForm(instance=obj)  #  form which would be shown in normal usage
data = the_magic_function(form0)  #  data which would be posted if user just pressed submit right away

# potentially manipulate some parts of this data to make the test interesting

form1 = MyForm(instance=obj, data=data)

# actual tests are on form1

form.initial is kinda what I'm looking for, but not quite: it contains Python objects rather than strings.

答案1

得分: 1

这不完全是你所要求的,但这段代码片段可能仍然对你有所帮助。我将其用于从表单响应创建新的POST数据。例如,当表单验证失败时,重新提交已校正的表单。

import lxml.html

def form_data(response: HttpResponse, **kwargs) -> dict:
    return parse_html_form(response.content, **kwargs)

def parse_html_form(html: str, **kwargs) -> dict:
    """将表单数据返回为字典。

    通过使用`kwargs`中的属性来筛选表单查找。
    """
    tree = lxml.html.fromstring(html)

    filter = " and ".join(f"@{key}='{val}'" for key, val in kwargs.items())
    form = tree.xpath(f"//form[{filter}]" if filter else "//form")[0]

    data = {}
    for key, element in form.inputs.items():
        match element.value:
            case lxml.html.CheckboxValues():
                data[key] = [sub.value for sub in element.value.group if sub.value]
            case lxml.html.MultipleSelectOptions():
                data[key] = list(element.value)
            case _:
                data[key] = element.value or ""
    return data

你可以在渲染的表单上使用它:

form0 = MyForm(instance=obj)
data = parse_from_html(form0.as_div())
英文:

It's not exactly what you asked for, but this code snippet might help you nonetheless. I use it for creating new POST data from a form response. For example, to resubmit the corrected form when the form validation failed.

import lxml.html

def form_data(response: HttpResponse, **kwargs) -> dict:
    return parse_html_form(response.content, **kwargs)


def parse_html_form(html: str, **kwargs) -> dict:
    """Returns form data as a dict.

    The form lookup can be narrowed down by using attributes to filter for
    as `kwargs`.
    """
    tree = lxml.html.fromstring(html)

    filter = " and ".join(f"@{key}='{val}'" for key, val in kwargs.items())
    form = tree.xpath(f"//form[{filter}]" if filter else "//form")[0]

    data = {}
    for key, element in form.inputs.items():
        match element.value:
            case lxml.html.CheckboxValues():
                data[key] = [sub.value for sub in element.value.group if sub.value]
            case lxml.html.MultipleSelectOptions():
                data[key] = list(element.value)
            case _:
                data[key] = element.value or ""
    return data

You could use it on the rendered form:

form0 = MyForm(instance=obj)
data = parse_from_html(form0.as_div())

huangapple
  • 本文由 发表于 2023年2月16日 17:56:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/75470551.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定