python - Django django.test 客户端post请求

标签 python django django-models django-forms django-views

在 hellowebapp.com 上工作

请使用 Django 测试客户端发布请求帮助测试有效的表单发布?

response = self.client.post('/accounts/create_thing/', { 'name': dummy_thing.name, 'description': dummy_thing.description, })

这是测试用例代码片段:

from django.test import TestCase, RequestFactory   
from django.contrib.auth.models import AnonymousUser, User
from collection.models import Thing
from .views import *
from collection.forms import ThingForm

class SampleTest(TestCase):
    def setUp(self):
        # Every test needs access to the request factory.
        self.factory = RequestFactory()
        self.dummy_user = User.objects.create_user(username='dummy', password='nothings')
        self.dummy_thing = Thing.objects.create(name="Dummy Book",
                                          description="Book For Dummies.",
                                          slug="dummy-book",
                                          user=self.dummy_user)
    def test_form(self):
        dummy_thing = Thing.objects.get(name="Dummy Book")
        form = ThingForm(instance=dummy_thing)
        self.assertFalse(form.is_valid()) # No data has been supplied yet.
        form = ThingForm({ 'name': dummy_thing.name, 'description': dummy_thing.description, }, instance=dummy_thing)
        self.assertTrue(form.is_valid())

    def test_form_post(self):
        dummy_thing = Thing.objects.get(name="Dummy Book")
        self.client.login(username=dummy_thing.user.username, password='nothings')

        # Test POST invalid data
        response = self.client.post('/accounts/create_thing/', { })
        self.assertFormError(response, 'form', 'name', 'This field is required.')
        self.assertFormError(response, 'form', 'description', 'This field is required.')
        self.assertTemplateUsed(response, 'things/create_thing.html')
        self.assertEqual(response.status_code, 200)

        # Test POST valid data? 
        # response = self.client.post('/accounts/create_thing/', { 'name': dummy_thing.name, 'description': dummy_thing.description, })
        # self.assertEqual(response.status_code, 200)

这是模型

models.py

class Thing(models.Model):
    name = models.CharField(max_length=255)
    description = models.TextField()
    slug = models.SlugField(unique=True)
    user = models.OneToOneField(User, blank=True, null=True)

注:user = models.OneToOneField(User, blank=True, null=True)

“Thing.user”必须是“User”实例。

列 user_id 必须是唯一的。

views.py

from django.contrib.auth.decorators import login_required
from django.http import Http404
from django.shortcuts import render, redirect
from django.template.defaultfilters import slugify

from collection.forms import ThingForm
from collection.models import Thing


def index(request):
    things = Thing.objects.all()
    return render(request, 'index.html', {
        'things': things,
    })


def thing_detail(request, slug):
    # grab the object...
    thing = Thing.objects.get(slug=slug)

    # and pass to the template
    return render(request, 'things/thing_detail.html', {
        'thing': thing,
    })


@login_required
def edit_thing(request, slug):
    # grab the object...
    thing = Thing.objects.get(slug=slug)

    # grab the current logged in user and make sure they're the owner of the thing
    if thing.user != request.user:
        raise Http404

    # set the form we're using...
    form_class = ThingForm

    # if we're coming to this view from a submitted form,  
    if request.method == 'POST':
        # grab the data from the submitted form
        form = form_class(data=request.POST, instance=thing)

        if form.is_valid():
            # save the new data
            form.save()
            return redirect('thing_detail', slug=thing.slug)

    # otherwise just create the form
    else:
        form = form_class(instance=thing)

    # and render the template
    return render(request, 'things/edit_thing.html', {
        'thing': thing,
        'form': form,
    })


def create_thing(request):
    form_class = ThingForm

    # if we're coming from a submitted form, do this
    if request.method == 'POST':
        # grab the data from the submitted form and apply to the form
        form = form_class(request.POST)

        if form.is_valid():
            # create an instance but do not save yet
            thing = form.save(commit=False)

            # set the additional details
            thing.user = request.user
            thing.slug = slugify(thing.name)

            # save the object
            thing.save()

            # redirect to our newly created thing
            return redirect('thing_detail', slug=thing.slug)

    # otherwise just create the form
    else:
        form = form_class()

    return render(request, 'things/create_thing.html', {
        'form': form,
    })


def browse_by_name(request, initial=None):
    if initial:
        things = Thing.objects.filter(
             name__istartswith=initial).order_by('name')
    else:
        things = Thing.objects.all().order_by('name')

    return render(request, 'search/search.html', {
        'things': things,
        'initial': initial,
    })

这是错误:

$ python manage.py test

.ECreating test database for alias 'default'...
Destroying test database for alias 'default'...

======================================================================
ERROR: test_form_post (collection.tests.SampleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "E:\Working\Python\Django\Python2.7\Hello-Web-App\GitHub\Test\hellowebapp-code-master\collection\tests.py", line 36, in test_form_post
    response = self.client.post('/accounts/create_thing/', { 'name': dummy_thing.name, 'description': dummy_thing.description, })
  File "C:\Python27\lib\site-packages\django\test\client.py", line 541, in post
    secure=secure, **extra)
  File "C:\Python27\lib\site-packages\django\test\client.py", line 343, in post
    secure=secure, **extra)
  File "C:\Python27\lib\site-packages\django\test\client.py", line 409, in generic
    return self.request(**r)
  File "C:\Python27\lib\site-packages\django\test\client.py", line 494, in request
    six.reraise(*exc_info)
  File "C:\Python27\lib\site-packages\django\core\handlers\exception.py", line 39, in inner
    response = get_response(request)
  File "C:\Python27\lib\site-packages\django\core\handlers\base.py", line 249, in _legacy_get_response
    response = self._get_response(request)
  File "C:\Python27\lib\site-packages\django\core\handlers\base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Python27\lib\site-packages\django\core\handlers\base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "E:\Working\Python\Django\Python2.7\Hello-Web-App\GitHub\Test\hellowebapp-code-master\collection\views.py", line 77, in create_thing
    thing.save()
  File "C:\Python27\lib\site-packages\django\db\models\base.py", line 796, in save
    force_update=force_update, update_fields=update_fields)
  File "C:\Python27\lib\site-packages\django\db\models\base.py", line 824, in save_base
    updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
  File "C:\Python27\lib\site-packages\django\db\models\base.py", line 908, in _save_table
    result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
  File "C:\Python27\lib\site-packages\django\db\models\base.py", line 947, in _do_insert
    using=using, raw=raw)
  File "C:\Python27\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:\Python27\lib\site-packages\django\db\models\query.py", line 1043, in _insert
    return query.get_compiler(using=using).execute_sql(return_id)
  File "C:\Python27\lib\site-packages\django\db\models\sql\compiler.py", line 1054, in execute_sql
    cursor.execute(sql, params)
  File "C:\Python27\lib\site-packages\django\db\backends\utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "C:\Python27\lib\site-packages\django\db\utils.py", line 94, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "C:\Python27\lib\site-packages\django\db\backends\utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "C:\Python27\lib\site-packages\django\db\backends\sqlite3\base.py", line 337, in execute
    return Database.Cursor.execute(self, query, params)
IntegrityError: column user_id is not unique

----------------------------------------------------------------------
Ran 2 tests in 0.687s

FAILED (errors=1)

此外,尝试了 Django shell 也是徒劳:

$ winpty python manage.py shell
Python 2.7.11 (v2.7.11:6d1b6a68f775, Dec  5 2015, 20:40:30) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.test import Client
>>> csrf_client = Client(enforce_csrf_checks=True)
>>> c.login(username="dummy", password='nothings')
>>> c = Client()
>>> c.login(username="dummy", password='nothings')
True
>>> response = c.post('http://127.0.0.1:8000/accounts/create_thing/', { 'name': 'dummy book', 'description': 'book for dummies' })
Internal Server Error: /accounts/create_thing/
Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\django\core\handlers\exception.py", line 39, in inner
    response = get_response(request)
  File "C:\Python27\lib\site-packages\django\core\handlers\base.py", line 249, in _legacy_get_response
    response = self._get_response(request)
  File "C:\Python27\lib\site-packages\django\core\handlers\base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Python27\lib\site-packages\django\core\handlers\base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "E:\Working\Python\Django\Python2.7\Hello-Web-App\GitHub\Test\hellowebapp-code-master\collection\views.py", line 77, in create_thing
    thing.save()
  File "C:\Python27\lib\site-packages\django\db\models\base.py", line 796, in save
    force_update=force_update, update_fields=update_fields)
  File "C:\Python27\lib\site-packages\django\db\models\base.py", line 824, in save_base
    updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
  File "C:\Python27\lib\site-packages\django\db\models\base.py", line 908, in _save_table
    result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
  File "C:\Python27\lib\site-packages\django\db\models\base.py", line 947, in _do_insert
    using=using, raw=raw)
  File "C:\Python27\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:\Python27\lib\site-packages\django\db\models\query.py", line 1043, in _insert
    return query.get_compiler(using=using).execute_sql(return_id)
  File "C:\Python27\lib\site-packages\django\db\models\sql\compiler.py", line 1054, in execute_sql
    cursor.execute(sql, params)
  File "C:\Python27\lib\site-packages\django\db\backends\utils.py", line 79, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "C:\Python27\lib\site-packages\django\db\backends\utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "C:\Python27\lib\site-packages\django\db\utils.py", line 94, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "C:\Python27\lib\site-packages\django\db\backends\utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "C:\Python27\lib\site-packages\django\db\backends\sqlite3\base.py", line 337, in execute
    return Database.Cursor.execute(self, query, params)
IntegrityError: column user_id is not unique
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "C:\Python27\lib\site-packages\django\test\client.py", line 541, in post
    secure=secure, **extra)
  File "C:\Python27\lib\site-packages\django\test\client.py", line 343, in post
    secure=secure, **extra)
  File "C:\Python27\lib\site-packages\django\test\client.py", line 409, in generic
    return self.request(**r)
  File "C:\Python27\lib\site-packages\django\test\client.py", line 494, in request
    six.reraise(*exc_info)
  File "C:\Python27\lib\site-packages\django\core\handlers\exception.py", line 39, in inner
    response = get_response(request)
  File "C:\Python27\lib\site-packages\django\core\handlers\base.py", line 249, in _legacy_get_response
    response = self._get_response(request)
  File "C:\Python27\lib\site-packages\django\core\handlers\base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Python27\lib\site-packages\django\core\handlers\base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "E:\Working\Python\Django\Python2.7\Hello-Web-App\GitHub\Test\hellowebapp-code-master\collection\views.py", line 77, in create_thing
    thing.save()
  File "C:\Python27\lib\site-packages\django\db\models\base.py", line 796, in save
    force_update=force_update, update_fields=update_fields)
  File "C:\Python27\lib\site-packages\django\db\models\base.py", line 824, in save_base
    updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
  File "C:\Python27\lib\site-packages\django\db\models\base.py", line 908, in _save_table
    result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
  File "C:\Python27\lib\site-packages\django\db\models\base.py", line 947, in _do_insert
    using=using, raw=raw)
  File "C:\Python27\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:\Python27\lib\site-packages\django\db\models\query.py", line 1043, in _insert
    return query.get_compiler(using=using).execute_sql(return_id)
  File "C:\Python27\lib\site-packages\django\db\models\sql\compiler.py", line 1054, in execute_sql
    cursor.execute(sql, params)
  File "C:\Python27\lib\site-packages\django\db\backends\utils.py", line 79, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "C:\Python27\lib\site-packages\django\db\backends\utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "C:\Python27\lib\site-packages\django\db\utils.py", line 94, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "C:\Python27\lib\site-packages\django\db\backends\utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "C:\Python27\lib\site-packages\django\db\backends\sqlite3\base.py", line 337, in execute
    return Database.Cursor.execute(self, query, params)
IntegrityError: column user_id is not unique

>>> from django.contrib.auth.models import User
>>> users = User.objects.all()
>>> users[1]
<User: dummy>
>>> response = c.post('http://127.0.0.1:8000/accounts/create_thing/', { 'name': 'dummy book', 'description': 'book for dummies', 'user_id': users[1].id })
Internal Server Error: /accounts/create_thing/
Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\django\core\handlers\exception.py", line 39, in inner
    response = get_response(request)
  File "C:\Python27\lib\site-packages\django\core\handlers\base.py", line 249, in _legacy_get_response
    response = self._get_response(request)
  File "C:\Python27\lib\site-packages\django\core\handlers\base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Python27\lib\site-packages\django\core\handlers\base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "E:\Working\Python\Django\Python2.7\Hello-Web-App\GitHub\Test\hellowebapp-code-master\collection\views.py", line 77, in create_thing
    thing.save()
  File "C:\Python27\lib\site-packages\django\db\models\base.py", line 796, in save
    force_update=force_update, update_fields=update_fields)
  File "C:\Python27\lib\site-packages\django\db\models\base.py", line 824, in save_base
    updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
  File "C:\Python27\lib\site-packages\django\db\models\base.py", line 908, in _save_table
    result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
  File "C:\Python27\lib\site-packages\django\db\models\base.py", line 947, in _do_insert
    using=using, raw=raw)
  File "C:\Python27\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:\Python27\lib\site-packages\django\db\models\query.py", line 1043, in _insert
    return query.get_compiler(using=using).execute_sql(return_id)
  File "C:\Python27\lib\site-packages\django\db\models\sql\compiler.py", line 1054, in execute_sql
    cursor.execute(sql, params)
  File "C:\Python27\lib\site-packages\django\db\backends\utils.py", line 79, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "C:\Python27\lib\site-packages\django\db\backends\utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "C:\Python27\lib\site-packages\django\db\utils.py", line 94, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "C:\Python27\lib\site-packages\django\db\backends\utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "C:\Python27\lib\site-packages\django\db\backends\sqlite3\base.py", line 337, in execute
    return Database.Cursor.execute(self, query, params)
IntegrityError: column user_id is not unique
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "C:\Python27\lib\site-packages\django\test\client.py", line 541, in post
    secure=secure, **extra)
  File "C:\Python27\lib\site-packages\django\test\client.py", line 343, in post
    secure=secure, **extra)
  File "C:\Python27\lib\site-packages\django\test\client.py", line 409, in generic
    return self.request(**r)
  File "C:\Python27\lib\site-packages\django\test\client.py", line 494, in request
    six.reraise(*exc_info)
  File "C:\Python27\lib\site-packages\django\core\handlers\exception.py", line 39, in inner
    response = get_response(request)
  File "C:\Python27\lib\site-packages\django\core\handlers\base.py", line 249, in _legacy_get_response
    response = self._get_response(request)
  File "C:\Python27\lib\site-packages\django\core\handlers\base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Python27\lib\site-packages\django\core\handlers\base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "E:\Working\Python\Django\Python2.7\Hello-Web-App\GitHub\Test\hellowebapp-code-master\collection\views.py", line 77, in create_thing
    thing.save()
  File "C:\Python27\lib\site-packages\django\db\models\base.py", line 796, in save
    force_update=force_update, update_fields=update_fields)
  File "C:\Python27\lib\site-packages\django\db\models\base.py", line 824, in save_base
    updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
  File "C:\Python27\lib\site-packages\django\db\models\base.py", line 908, in _save_table
    result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
  File "C:\Python27\lib\site-packages\django\db\models\base.py", line 947, in _do_insert
    using=using, raw=raw)
  File "C:\Python27\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:\Python27\lib\site-packages\django\db\models\query.py", line 1043, in _insert
    return query.get_compiler(using=using).execute_sql(return_id)
  File "C:\Python27\lib\site-packages\django\db\models\sql\compiler.py", line 1054, in execute_sql
    cursor.execute(sql, params)
  File "C:\Python27\lib\site-packages\django\db\backends\utils.py", line 79, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "C:\Python27\lib\site-packages\django\db\backends\utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "C:\Python27\lib\site-packages\django\db\utils.py", line 94, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "C:\Python27\lib\site-packages\django\db\backends\utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "C:\Python27\lib\site-packages\django\db\backends\sqlite3\base.py", line 337, in execute
    return Database.Cursor.execute(self, query, params)
IntegrityError: column user_id is not unique
>>>exit()

谢谢

最佳答案

发生这种情况是因为您有 OneToOneField,因为您的每个新 Thing 都必须连接到之前未选择的 User。所以因为你已经有 dummy_thingdummy_user 作为 User,你不能用相同的 Thing 保存新的实例 虚拟用户

我相信你的意图是每个 Thing 都有一个 User,所以你应该使用 ForeignKey 而不是 OneToOneField.

但如果我错了,如果你真的需要 OneToOneField,那么要测试你的 POST 请求,只需创建新用户并以新用户身份登录,然后 thing.user = request.user 将采用 dummy_user2 并且不会与唯一值发生冲突。

class SampleTest(TestCase):
    def setUp(self):
        # Every test needs access to the request factory.
        self.factory = RequestFactory()
        self.dummy_user = User.objects.create_user(username='dummy', password='nothings')
        self.dummy_thing = Thing.objects.create(name="Dummy Book",
                                          description="Book For Dummies.",
                                          slug="dummy-book",
                                          user=self.dummy_user)
        self.dummy_user2 = User.objects.create_user(username='dummy2', password='nothing')

    def test_form_post(self):
        dummy_thing = Thing.objects.get(name="Dummy Book")
        self.client.login(username=dummy_thing2.user.username, password='nothing')

        # Test POST invalid data
        response = self.client.post('/accounts/create_thing/', { })
        self.assertFormError(response, 'form', 'name', 'This field is required.')
        self.assertFormError(response, 'form', 'description', 'This field is required.')
        self.assertTemplateUsed(response, 'things/create_thing.html')
        self.assertEqual(response.status_code, 200)

        # Test POST valid data? 
        response = self.client.post('/accounts/create_thing/', { 'name': 'new name', 'description': 'new description', })
        self.assertEqual(response.status_code, 200)

关于python - Django django.test 客户端post请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40005411/

相关文章:

python - 计算数据框中的斜率

python - 如何理解 Django View 函数的配置文件输出

Django InlineModelAdmin 给出错误 'MediaDefiningClass' 对象不可迭代

python - 预取某些对象返回空值

django - 如何在 Django 模型中获取 upload_to 的当前日期

python - pip 安装与 conda 安装

python - 工厂模式在 Python 中没有意义吗?

python - 在 python 中进行列表理解时扩展列表

python - 如何修复 : Cannot resolve keyword 'user' into field. 选择为 : description, end_time、id、start_time、title Django 错误

Django admin 内联自定义查询集