首頁 後端開發 Python教學 看看 Python Django開發 異常及解決辦法

看看 Python Django開發 異常及解決辦法

Jan 07, 2021 am 10:25 AM
python

看看 Python Django開發 異常及解決辦法

相關免費學習推薦:python影片教學

1.Django xadmin資料遷移報錯ImportError: cannot import name 'QUERY_TERMS'

在進行Django xadmin資料遷移時報錯:

from django.db.models.sql.query import LOOKUP_SEP, QUERY_TERMS
ImportError: cannot import name 'QUERY_TERMS' from 'django.db.models.sql.query' (C:\Users\LENOVO\.virtualenvs\Django_Vue_Fresh_Ecommerce-NKba4OvD\lib\site-packages\django\db\models\sql\query.py)
登入後複製

由於xadmin的更新跟不上Django的更新,因此導致了xadmin的許多程式碼出錯,需要進行修改,這裡將xadmin\plugins\filters.py中from django.db.models.sql.query import LOOKUP_SEP, QUERY_TERMS#修改為from django.db.models.sql.query import LOOKUP_SEP, Query,也需要將47行的if len(parts) > 1 and parts[-1] in Query:修改為if len(parts) > 1 and parts[-1] in QUERY_TERMS:

2.Django xadmin報錯TypeError: render() got an unexpected keyword argument 'renderer'

在Django登入進入xadmin後台時,在新增小工具時,會報錯,如下:

return widget.render(TypeError: render() got an unexpected keyword argument 'renderer'
登入後複製

解決方法有兩種:

  • 修改Django原始碼
    找到lib\site-packages\django\forms\boundfield.py,找到第96行,註解掉即可,如下:
return widget.render(
    name=self.html_initial_name if only_initial else self.html_name,
    value=self.value(),
    attrs=attrs,
    # renderer=self.form.renderer,)
登入後複製

此時再點擊Add Budgets就不會再報錯了。

  • 修改xadmin程式碼
    在xadmin/views/dashboard.py中修改render()函數,第36行改為def render(self, name , value, attrs=None, renderer=None):,即增加renderer參數為None。

兩種方法皆可,但個人建議採用第二種方法,因為xadmin是外部引入到extra_apps作為外部的app,本身就可能經過了一定修改,在此基礎上再修改也影響不大,而django是虛擬環境所帶的依賴庫,相當於系統文件,因此不要輕易修改。

3.Django xadmin報錯RuntimeError: isn't in an application in INSTALLED_APPS.

##在進行資料庫對應時,報錯如下:

raise RuntimeError(RuntimeError: Model class django.contrib.admin.models.LogEntry doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.
登入後複製
#解決方法是在settings.py中的INSTALLED_APPS中增加

django.contrib.admin,如下:

INSTALLED_APPS = [
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'apps.users.apps.UsersConfig',
    'goods',
    'trade',
    'user_operation',
    'DjangoUeditor',
    'xadmin',
    'crispy_forms',
    'django.contrib.admin']
登入後複製

4.Django配置Restful framework報錯__str__ returned non-string ( type NoneType)

在Django專案中配置Restful framework時,報錯__str__ returned non-string (type NoneType),如下:


看看 Python Django開發 異常及解決辦法 這可能是自訂用戶當模型取代Django自帶的使用者模型時,允許name(或相似的)欄位允許為空,例如
name = models.CharField(max_length=30, null=True, blank=True, verbose_name='姓名') 所以會回傳non-string報錯,完整模型如下:

class UserProfile(AbstractUser):
    '''用户'''
    name = models.CharField(max_length=30, null=True, blank=True, verbose_name='姓名')
    birthday = models.DateField(null=True, blank=True, verbose_name='出生日期')
    gender = models.CharField(max_length=6, choices=(('male', u'男'), ('female', u'女')), default='female',
                              verbose_name='性别')
    mobile = models.CharField(max_length=11, verbose_name='电话')
    email = models.CharField(max_length=50, null=True, blank=True, verbose_name='邮箱')

    is_delete = models.BooleanField(default=False, verbose_name='是否删除')

    class Meta:
        verbose_name = '用户'
        verbose_name_plural = '用户'

    def __str__(self):
        return self.name
登入後複製
解決方法有2種:

    退出admin或xadmin後台登入
  • 登出後台管理登錄,操作如下:

    django xadmin logout
  • 修改使用者模型
  • __str__()方法 因為自訂使用者如UserProfile繼承自AbstractUser,而AbstractUser模型有username屬性,不允許為空,所以可以設定為回傳
    self.username,即如下:
def __str__(self):
    return self.username
登入後複製
此時不登出後台管理也可以正常存取。

5.DRF封包錯誤AssertionError: basename argument not specified

在Restful framework中使用篩選器報錯誤:

assert queryset is not None, '`basename` argument not specified, and could ' \
AssertionError: `basename` argument not specified, and could not automatically determine the name from the viewset, as it does not have a `.queryset` attribute.
登入後複製
報錯提示很明顯,

assert queryset不是None,未指定「basename」參數,顯然需要在使用router定義路由時指定basename參數,如下:

router = DefaultRouter()# 配置goods的路由router.register(r'goods', GoodsListViewSet, basename='goods')
登入後複製
即在urls.py中使用router設定路由時加入basename參數即可。

6.UnorderedObjectListWarning: Pagination may yield inconsistent results with an unordered object_list

paginator = self.django_paginator_class(queryset, page_size)#dameDamejwork 在實作Dameango 在實作Dameango Rful視圖時對某一類資料進行分頁並在前端請求存取資料時顯示警告資訊如下:

XXX\lib\site-packages\rest_framework\pagination.py:200: UnorderedObjectListWarning: Pagination may yield inconsistent results with an unordered object_list: <class> QuerySet.
  paginator = self.django_paginator_class(queryset, page_size)</class>
登入後複製

提示的是無序物件清單警告,意思是對資料結果進行排序,在views.py中取資料時加入排序即可,預設可以依照id排序,示意如下:
class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
    '''商品列表页,并实现分页、搜索、过滤、排序'''

    queryset = Goods.objects.filter(is_delete=False).order_by('id')  # 添加根据id排序即可
    serializer_class = GoodsSerializer
    pagination_class = GoodsPagination
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filter_class = GoodsFilter
    search_fields = ['name', 'goods_brief', 'goods_desc']
    ordering_fields = ['sold_num', 'shop_price']
登入後複製

此時再運行,不再顯示警告訊息。

7.Django Restful framework中使用JWT實作自訂驗證{「non_field_errors」:[「無法使用提供的認證資訊登入。」]}

#先聲明小編使用的Django版本為3.0,後面有用。

在DRF中使用驗證時常會使用JSON Web Token進行驗證,settings.py配置如下:

# DRF配置REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'],
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ]}# 自定义用户认证配置AUTHENTICATION_BACKENDS = [
    'users.views.CustomBackend',]
登入後複製

apps/users/views.py如下:
from django.db.models import Qfrom django.contrib.auth.backends import ModelBackendfrom django.contrib.auth import get_user_model


User = get_user_model()# Create your views here.class CustomBackend(ModelBackend):
    '''自定义用户验证'''

    def authenticate(self, username=None, password=None, **kwargs):
        try:
            print(123)
            user = User.objects.get(Q(username=username)|Q(mobile=username))
            if user.check_password(password) and user.is_delete != True:
                print(456)
                return user        except Exception as e:
            return None
登入後複製

urls.py配置如下:

from rest_framework_jwt.views import obtain_jwt_token

urlpatterns = [
       # JWT认证路由
       url(r'^login/', obtain_jwt_token),]
登入後複製

但是在模拟请求访问时却未收到token,只提示错误信息{"non_field_errors":["无法使用提供的认证信息登录。"]},这让我很苦恼,明明所有配置都没问题啊,百思不得姐,到底哪里出了问题了呢?一直不停的排错、Debug,却还是一样的错误,这让我很郁闷。最后不得不去求助于JWT官方文档,看到环境要求仿佛有点儿感觉了:

Requirements
Python (2.7, 3.3, 3.4, 3.5)
Django (1.8, 1.9, 1.10)
Django REST Framework (3.0, 3.1, 3.2, 3.3, 3.4, 3.5)

这里要求的最高Django版本为1.9,而我自己的Django版本为3.0,凭直觉立马想到会不会是版本不兼容的问题,导致了某些地方不一致。jwt部分就不说了,本身版本没怎么更新,可能问题出在了Django和DRF上面,而最有可能出问题的就是自定义验证类,CustomBackend继承自ModelBackend,于是我到django.contrib.auth.backends源码中查看,其定义如下:

class ModelBackend(BaseBackend):
    """
    Authenticates against settings.AUTH_USER_MODEL.
    """

    def authenticate(self, request, username=None, password=None, **kwargs):
        if username is None:
            username = kwargs.get(UserModel.USERNAME_FIELD)
        if username is None or password is None:
            return
        try:
            user = UserModel._default_manager.get_by_natural_key(username)
        except UserModel.DoesNotExist:
            # Run the default password hasher once to reduce the timing
            # difference between an existing and a nonexistent user (#20760).
            UserModel().set_password(password)
        else:
            if user.check_password(password) and self.user_can_authenticate(user):
                return user	...
登入後複製

为了验证是否是版本的问题,我在系统环境中安装了JWT指定的Django版本1.9用于进行对比,再查看django.contrib.auth.backends.py:

class ModelBackend(object):
    """
    Authenticates against settings.AUTH_USER_MODEL.
    """

    def authenticate(self, username=None, password=None, **kwargs):
        UserModel = get_user_model()
        if username is None:
            username = kwargs.get(UserModel.USERNAME_FIELD)
        try:
            user = UserModel._default_manager.get_by_natural_key(username)
            if user.check_password(password):
                return user        except UserModel.DoesNotExist:
            # Run the default password hasher once to reduce the timing
            # difference between an existing and a non-existing user (#20760).
            UserModel().set_password(password)
登入後複製

到现在,你们是否发现了什么(^_^)?

哈哈,你猜的没错,是新版中的authenticate()方法发生了改变,增加了request参数,而自定义验证类时就是继承ModelBackend类并重写authenticate()方法,而我使用的参数采用的是老版本中的参数,与本应继承的新版本中的方法参数不一致,所以就不是重写是重载了,所以在请求时验证调用的方法并不是自定义的authenticate(),而是ModelBackend类中的authenticate()方法明白怎么回事了就赶紧改了试试,再次测试{"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoxNTk1ODk2MTc3LCJlbWFpbCI6IjEyM0AxMjMuY29tIn0.pblxNy4s4XBrqmnsfI9-dmx3Q8rErqq1WbN4rfBSZfI"},一片光明,真是版本不兼容害苦了我,以后得注意了。

8.Django使用DRF实现注册功能报错Got AttributeError when attempting to get a value

在使用DRF实现注册功能时,前端的用户名(手机号)、验证码、邮箱传到后端处理时,由于验证码不属于用户的一个字段,但是为了验证又必须设置该字段,如果不注意,就容易报错,一般如下:

raise type(exc)(msg)AttributeError: Got AttributeError when attempting to get a value for field `code` on serializer `UserRegSerializer`.The serializer field might be named incorrectly and not match any attribute or key on the `UserProfile` instance.Original exception text was: 'UserProfile' object has no attribute 'code'.
登入後複製

报错提示很明显,UserProfile没有code属性。具体来说,这是因为Meta中指定了fields = ['username', 'code', 'mobile', 'password'],包含code字段,而在验证时为了判断验证码的正误而临时加入code字段,但是在validate(attrs)又将其删去,导致在序列化时找不到code字段,因此出错,这是需要将字段的write_only设置True,以确保在更新或创建实例时可以使用该字段,但是在序列化表示形式时不包括该字段,即设置为如下即可:

code = serializers.CharField(max_length=4, min_length=4, write_only=True, label='验证码',
    help_text='验证码',
    error_messages={
        'required': '请输入验证码',
        'blank': '请输入验证码',
        'max_length': '请输入4位验证码',
        'min_length': '请输入4位验证码'
    })
登入後複製

9.DRF访问文档路由报错AttributeError: ‘AutoSchema’ object has no attribute ‘get_link’

DRF提供了文档功能,无需再专门写文档即可同步使用文档,但是在访问http://127.0.0.1:8000/docs/的时候可能报错:

    link = view.schema.get_link(path, method, base_url=self.url)AttributeError: 'AutoSchema' object has no attribute 'get_link'
登入後複製

此时需要在settings.py中进行配置:

# DRF配置REST_FRAMEWORK = {
    ...
    'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.AutoSchema',
    ...}
登入後複製

重新加载之后再次访问就会访问到文档页面,如下:
DRF 文档

10.DRF动态设置权限

在DRF中经常会用到权限,一般情况下是在视图ViewSet类下设置属性permission_classes = [IsAuthenticated, IsOwnerOrReadOnly],但是这对于请求的所有方法(如create、retrieve、list)均有效,不能对不同的方法进行不同的限制,因此可以进行动态设置权限,即重写get_permissions()方法,针对不同地方法返回不同的权限,如下:

    def get_permissions(self):
        '''动态设置权限'''
        if self.action == 'retrieve':
            return [IsAuthenticated]
        elif self.action == 'create':
            return []
        return []
登入後複製

但是会报错如下:

if not permission.has_permission(request, self):TypeError: has_permission() missing 1 required positional argument: 'view'
登入後複製

这是因为返回的可能是权限类,即return [IsAuthenticated],这里只是返回了一个权限类,并没有实例化,即没有初始化,导致APIView在初始化时没有传入正确的权限,因此报错,修改为return [IsAuthenticated()]、返回实例化后的对象即可。

以上是看看 Python Django開發 異常及解決辦法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

PHP和Python:解釋了不同的範例 PHP和Python:解釋了不同的範例 Apr 18, 2025 am 12:26 AM

PHP主要是過程式編程,但也支持面向對象編程(OOP);Python支持多種範式,包括OOP、函數式和過程式編程。 PHP適合web開發,Python適用於多種應用,如數據分析和機器學習。

在PHP和Python之間進行選擇:指南 在PHP和Python之間進行選擇:指南 Apr 18, 2025 am 12:24 AM

PHP適合網頁開發和快速原型開發,Python適用於數據科學和機器學習。 1.PHP用於動態網頁開發,語法簡單,適合快速開發。 2.Python語法簡潔,適用於多領域,庫生態系統強大。

Python vs. JavaScript:學習曲線和易用性 Python vs. JavaScript:學習曲線和易用性 Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

PHP和Python:深入了解他們的歷史 PHP和Python:深入了解他們的歷史 Apr 18, 2025 am 12:25 AM

PHP起源於1994年,由RasmusLerdorf開發,最初用於跟踪網站訪問者,逐漸演變為服務器端腳本語言,廣泛應用於網頁開發。 Python由GuidovanRossum於1980年代末開發,1991年首次發布,強調代碼可讀性和簡潔性,適用於科學計算、數據分析等領域。

vs code 可以在 Windows 8 中運行嗎 vs code 可以在 Windows 8 中運行嗎 Apr 15, 2025 pm 07:24 PM

VS Code可以在Windows 8上運行,但體驗可能不佳。首先確保系統已更新到最新補丁,然後下載與系統架構匹配的VS Code安裝包,按照提示安裝。安裝後,注意某些擴展程序可能與Windows 8不兼容,需要尋找替代擴展或在虛擬機中使用更新的Windows系統。安裝必要的擴展,檢查是否正常工作。儘管VS Code在Windows 8上可行,但建議升級到更新的Windows系統以獲得更好的開發體驗和安全保障。

visual studio code 可以用於 python 嗎 visual studio code 可以用於 python 嗎 Apr 15, 2025 pm 08:18 PM

VS Code 可用於編寫 Python,並提供許多功能,使其成為開發 Python 應用程序的理想工具。它允許用戶:安裝 Python 擴展,以獲得代碼補全、語法高亮和調試等功能。使用調試器逐步跟踪代碼,查找和修復錯誤。集成 Git,進行版本控制。使用代碼格式化工具,保持代碼一致性。使用 Linting 工具,提前發現潛在問題。

notepad 怎麼運行python notepad 怎麼運行python Apr 16, 2025 pm 07:33 PM

在 Notepad 中運行 Python 代碼需要安裝 Python 可執行文件和 NppExec 插件。安裝 Python 並為其添加 PATH 後,在 NppExec 插件中配置命令為“python”、參數為“{CURRENT_DIRECTORY}{FILE_NAME}”,即可在 Notepad 中通過快捷鍵“F6”運行 Python 代碼。

vscode 擴展是否是惡意的 vscode 擴展是否是惡意的 Apr 15, 2025 pm 07:57 PM

VS Code 擴展存在惡意風險,例如隱藏惡意代碼、利用漏洞、偽裝成合法擴展。識別惡意擴展的方法包括:檢查發布者、閱讀評論、檢查代碼、謹慎安裝。安全措施還包括:安全意識、良好習慣、定期更新和殺毒軟件。

See all articles