解决VSCode编写Django代码时经常提示objects属性等不存在的错误

2018/04/29 posted in  Django学习

Django问题集锦

  1. Csrf验证

    需要在表单中加入`csrfmiddlewaretoken`或者在http头中`X-CSRFToken`请求头,具体值来自cookie当中的`csrftoken`
    
  2. Django允许跨域

    安装django-cors-headers

    pip install django-cors-headers
    

    在setting.py中增加如下代码

    INSTALLED_APPS = [
    ...
    'corsheaders',
    ...
    ]
    MIDDLEWARE_CLASSES = (
    ...
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware', # 注意顺序
    ...
    )
    #跨域增加忽略
    CORS_ALLOW_CREDENTIALS = True
    CORS_ORIGIN_ALLOW_ALL = True
    CORS_ORIGIN_WHITELIST = (
    '*'
    )
    CORS_ALLOW_METHODS = (
    'DELETE',
    'GET',
    'OPTIONS',
    'PATCH',
    'POST',
    'PUT',
    'VIEW',
    )
    CORS_ALLOW_HEADERS = (
    'XMLHttpRequest',
    'X_FILENAME',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
    'Pragma',
    )
  3. axios 默认支持csrf功能,需要修改其属性和服务器返回的csrfcookiename一致

    #Django返回的cookie中的csrf字段名字为csrftoken,会从request的header中读取X-CSRFTOKEN来校验csrf
    axios.defaults.xsrfHeaderName = "X-CSRFTOKEN";
    axios.defaults.xsrfCookieName = "csrftoken";

    如果axios要访问的接口和前端页面属于跨域状态,那么axios无法读取xsrfCookie,则也无法设置xsrfHeader,此时则需要后端将csrftoken放入response中而不是cookie当中,axios在request阻截器中手动设置xsrfHeader

  4. Django使用django-rest-framework 单独某个view取消csrf验证

    需要两步:

    • 关掉django的csrf验证,利用@csrf_exempt(针对function view),或者用@method_decorator(csrf_exempt, name="dispatch")(针对class view)
    • 关掉drf框架的验证,在class view 中将authentication_classes设置为BasicAuthentication
    @method_decorator(csrf_exempt, name="dispatch")
    class login(views.APIView):
    authentication_classes = (BasicAuthentication,)
    def post(self, request, *args, **kwargs):
    username = request.data.get("username")
    password = request.data.get("password")
    user = auth.authenticate(request, username=username, password=password)
    if user is not None:
    auth.login(request, user)
    return ErosResponse()
    else:
    return ErosResponse(status=ErosResponseStatus.INVALID_USER)
  5. 使用OrderFilter过程中遇到OrderingFilter object has no attribute 'filter_queryset':

    需要使用从rest_framework.filters中导入的OrderingFilter,而不是django_filters

    from django_filters.rest_framework import DjangoFilterBackend
    from rest_framework.filters import OrderingFilter
    
  6. Django链接Mysql 8.0 出现错误(1045:Access denied for user 'root'@'localhost' (using password: NO) 的一种解决方法

    出现此错误的原因是MySQL8.0 密码的加密方式发生了改变,采用了cha2加密方法,我们可以利用下面的语句将MySQL的密码加密方式修改为之前的版本

    mysql -u root -p
    use mysql;
    ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'newpassword';
    FLUSH PRIVILEGES;
  7. Django-Filter自定义查询过滤字段

    from django_filters import FilterSet
    from django_filters import CharFilter
    class TagFilter(FilterSet):
    ##自定义search字段
    search = CharFilter(name="name", lookup_expr="contains")
    class Meta:
    model = Tag
    fields = {
    'id': ['exact'],
    'name': ['exact', 'contains'],
    'search': ['exact'],
    }

    具体Django-Filter的用法可以参考文档

  8. DRF的OrderingFilter默认排序

    filter_backends = (DjangoFilterBackend, OrderingFilter)
    ordering_fields = ('id', 'hot')
    ordering = ('-hot',)
  9. Django runserver指定setting配置

    python3 manage.py runserver 0.0.0.0:8000 --settings=OrionGraphQL.settings.dev
    
2018/04/23 posted in  Django学习

Django 发送html格式的邮件

django中默认提供了发送邮件的库mail,通过这个库我们可以很方便的通过django发送一份电子邮件

1. 在setting 中指定邮件服务器的基本信息
EMAIL_USE_SSL = True    
EMAIL_HOST = 'smtp.exmail.qq.com'  # 如果是 163 改成 smtp.163.com
EMAIL_PORT = 465
EMAIL_HOST_USER = '***@domain.com' # 帐号
EMAIL_HOST_PASSWORD = 'password'  # 密码
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
2. 引用mail库发送邮件
from django.core.mail import EmailMessage
from Across.settings import EMAIL_HOST_USER

msg = EmailMessage("邮件标题","邮件内容",EMAIL_HOST_USER,[接受邮件列表])
msg.send()
3.发送html模板邮件

可以利用Django的template库读取指定的html模板,然后将参数代入,首选需要在settings中设置template的目录

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            os.path.join(BASE_DIR,'templates')  ##你的模板目录
        ],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

然后将你准备好的html模板放入该目录,然后就是利用temlate的loader函数加载模板传入指定参数

html_content = loader.render_to_string('email.html',{'authcode':random,'title':"标题标题",'operation':operation_str})
msg = EmailMessage("您的验证码",html_content,EMAIL_HOST_USER,[email])
msg.content_subtype = "html" # Main content is now text/html
msg.send()
2017/11/29 posted in  Django学习

Django扩展默认的User Model

Django中为我们默认提供了用户模块User,但是其当中的字段可能并不能完全满足我们的需求,这时我们就需要自定义一个User Model出来,如果你对自带的User模型很满意,仅仅是需要添加几个额外的字段,你就可以新建一个model类继承AbstractUser, 或者你完全不需要User模型中提供的类似first_namelast_name这些字段,你可以将model类继承AbstractBaseUser,这样只会保留password,last_login,is_active这三个字段。

本文介绍的是继承自AbstractUser的用法

在models.py中新建一个model继承自AbstractUser

from django.db import models

# Create your models here.
from django.contrib.auth.models import AbstractUser
from enum import Enum


class UserProfile(AbstractUser):

    GENDER = [
        (0,"未知"),
        (1,"男性"),
        (2,"女性")
    ]

    nickname = models.CharField(max_length=50)
    intro = models.CharField(max_length=500)
    mobile = models.CharField(max_length=13)
    gender = models.IntegerField(choices=GENDER,default=0)

    REQUIRED_FIELDS = ['nickname', 'intro', 'mobile', 'gender']

在setting.py中设置 AUTH_USER_MODEL

AUTH_USER_MODEL = 'User.UserProfile'
2017/11/27 posted in  Django学习