Skip to content

Blog Công Nghệ

MENUMENU
  • Trang chủ
  • Giới Thiệu
  • Lập Trình
    • Lập Trình Website
      • Laravel
        • Phân Tích Dự Án
      • PHP
      • SQL
      • HTML
      • CSS
      • Javascipt
      • My Project
      • Wordpress
    • Luyện Skill
    • Lập trình winform
    • CSDL
    • Lập Trình Android
    • Trí tuệ nhân tạo
    • Khai Khoáng Dữ Liệu
    • Arduino
    • Khác
    • Đồ án
  • Phần Mềm
    • Powerpoint
    • Tool
  • Cuộc sống và Giải trí
    • Hợp âm
    • web5ngay - youtube
    • Công Giáo
    • Kỹ Năng Sống
    • Street Workout
  • Danh sách bài viết
  • Guide line
    • Guild line phỏng vấn
    • Guide lines Laravel
    • Guide line Module Frontend
  • Tóm tắt sách
  • Fanpage

Blog Công Nghệ

Nơi chia sẻ kiến thức

Django – build core

13 Tháng Ba, 2024 by admin
Lượt xem: 55

Contents

  • 1. Django basic
  • 2. Thư viện MarshMallow – Validate
  • 3. Serializer
  • 4. Middleware
  • 5. Locale
  • 6. Migration
  • 7. Route
  • 8. Log
  • 9. env
  • 11. Queue/Jobs
  • 10. Models
  • 11. Template
  • 12. Kinh nghiệm khác
    • 12.1 Login Microsoft Entry

1. Django basic

Cài đặt python

https://www.freecodecamp.org/news/how-to-install-python-in-windows-operating-system/

// tạo environment
python -m venv venv

// active
venv\Scripts\activate.bat
  
// install django
pip install django
  
// tạo project tên mysite
django-admin startproject mysite
// Tạo app todo
python manage.py startapp todo
// start server
python manage.py runserver
  
// run server with host
python manage.py runserver localhost:8000
// create user admin account
python manage.py createsuperuser

// check django version
python -m django --version
  
// tạo file package sử dụng trong project
pip freeze > installed_packages.txt
// check connect database
python manage.py check --database default

// chạy lệnh dưới cmd như tinker của laravel
python manage.py shell

Try catch:

class TodoController(View):
    def get(self, request):
        try:
            dataTodo = TodoRepository.all()
            return ApiService.jsonData(dataTodo, _('messages.ok'))
        except Exception as e:
            LogService.error(str(e))
            return ApiService.jsonError(_('errors.default_error'))

2. Thư viện MarshMallow – Validate

Install

pip install marshmallow
from marshmallow import Schema, fields, validate, validates, ValidationError

class TodoRequest(Schema):
    name = fields.Str(validate=validate.OneOf(['Todo']))
    email = fields.Email(error_messages={
          'invalid': 'Custom message',
    })
    created_at = fields.DateTime()
    age = fields.Integer(required=True, error_messages={
          'required': 'custom message',
    })

    @validates('age')
    def validate_age(self, value):
        if value < 0:
            raise ValidationError('Age must be greater than 0')
        elif value > 30:
            raise ValidationError('Age must not be greater than 30')
        
    # class Meta:
    #     strict=True

3. Serializer

Convert data từ python sang json.

Cần cài rest_framework

pip install djangorestframework

Tạo file TodoSerializer.py

from rest_framework import serializers
from app.http.models.Todo import Todo

class TodoSerializer(serializers.ModelSerializer):
    title = serializers.CharField(max_length=100)
    status = serializers.BooleanField()
    date = serializers.DateTimeField()
    created_at = serializers.DateTimeField()
    updated_at = serializers.DateTimeField()
    class Meta:
        model = Todo
        # fields = ( 'title', 'status', 'date', 'created_at', 'updated_at')
        exclude = ()
        read_only_fields = () 

Sử dụng:

from app.http.models.Todo import Todo
from app.http.serializers.TodoSerializer import TodoSerializer
from app.services.LogService import LogService

class TodoRepository:
    ## 
    # get all data
    # Author HaoDT
    ##
    @staticmethod
    def all():
        try:
            dataTodo = Todo.objects.all()
            serializer = TodoSerializer(dataTodo, many=True)
            return serializer.data
        except Exception as e:
            LogService.error(str(e))
            return {}

4. Middleware

Định nghĩa middleware

from app.services.ApiService import ApiService
from http import HTTPStatus
from django.utils.translation import gettext_lazy as _

class UserMiddleware:

    def __init__(self, get_response):
        self.get_response = get_response
        # One-time configuration and initialization.

    def __call__(self, request):
        response = self.get_response(request)
        if request.path.startswith('/admin/'):
            # Code to be executed for each request before
            # the view (and later middleware) are called.

            print("This is demo middleware in Django")
            # Code to be executed for each request/response after
            # the view is called.
            if False:
                return ApiService.jsonMessage(_('errors.unauthorized'), HTTPStatus.UNAUTHORIZED)

        return response

    def process_exception(self, request, exception):
        pass

    def process_template_response(self, request, response):
        pass

add vào file settings.py

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'core_django.middlewares.UserMiddleware',
]

5. Locale

  1. Download gettext and install

# add to setting.py
from posixpath import abspath, dirname

DJANGO_ROOT = dirname(dirname(abspath(__file__)))
SITE_ROOT = dirname(DJANGO_ROOT)
USE_I18N = True

LOCALE_PATHS = (
    SITE_ROOT + '/locale',
)

ugettext = lambda s: s
LANGUAGES = (
    ('en', ugettext('English')),
    ('ja', ugettext('Japan')),
)


# hoặc
#__app
#__core_django
#_____settings.py

PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))

LOCALE_PATHS = (
    '../app/locale', # folder app
)

ugettext = lambda s: s
LANGUAGES = (
    ('en', ugettext('English')),
    ('ja', ugettext('Japan')),
)
// change language
LANGUAGE_CODE = 'ja'
// lệnh tạo language => thay ja bằng code lang tương ứng. (ở đây là ja => japan)
python manage.py makemessages -l ja

Có tạo file .po trong folder locale

Cấu trúc file .po

# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-02-21 13:45+0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
############ ERRORS ############
msgid "errors.default_error"
msgstr "エラーが発生しました。該当のデータが存在しません。"

msgid "errors.unauthorized"
msgstr "unauthorized"


############ MESSAGES ############
msgid "messages.created_failed"
msgstr "更新中にエラーが発生しました。"

msgid "messages.add_success"
msgstr "追加完了しました。"

msgid "messages.updated_success"
msgstr "情報の更新が完了しました。"

msgid "messages.updated_failed"
msgstr "更新中にエラーが発生しました。"

msgid "messages.deleted_success"
msgstr "削除完了しました。"

msgid "messages.deleted_failed"
msgstr "削除できません。"

msgid "messages.ok"
msgstr "ok"

Gồm 2 thành phần

+ msgid => key

+ msgstr => text translate

Sau đó chạy lệnh để build:

python manage.py compilemessages
  
// restart lại server
python manage.py runserver

Sử dụng:

_(key)
  
  
from django.utils.translation import gettext_lazy as _
  
return ApiService.jsonError(_('errors.default_error'))

6. Migration

Tạo models

from django.db import models
from django.utils import timezone

class Todo(models.Model):
    title = models.CharField(max_length=100)
    status = models.BooleanField()
    date = models.DateTimeField(default=timezone.now)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
 
    def __str__(self):
        return self.title

Chạy build

// build model sang migrate
python manage.py makemigrations

Chạy migrate

// migrate to db
python manage.py migrate

Rollback to zero:

# thay app thành tên ứng dụng của bạn
python manage.py migrate app zero 
  
python manage.py migrate user 0003_alter_user_created_at_alter_user_deleted_at_and_more 

7. Route

File urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('app.routes.index')),
]
  
  
urlpatterns = [
    path('admin/', admin.site.urls),
    path('be/', include([
        path('', include('apps.user.urls')),
        path('', include('apps.facility.urls')),
        path('', include('apps.common.urls')),
    ])),
    path('oauth2/', include('django_auth_adfs.urls')),
]
# File app.routes.index
from django.urls import path
from .api_v1 import apiV1


urlpatterns = [] + apiV1
# File app.routes.api_v1
from django.urls import path
from app import views

prefix = 'api/v1/'
apiV1 = [
    path(prefix + 'todo/', views.TodoController.as_view(), name = 'todo'),
    path(prefix + 'todo/test-validate/', views.TodoController.testValidate, name = 'todoTestValidate'),
]

8. Log

add vào setting.py

LOGGING = {
    "version": 1,
    "disable_existing_loggers": False,
    "formatters": {
        "verbose": {
            "format": "{levelname} {asctime} {module} {process:d} {thread:d} {message}",
            "style": "{",
        },
        "simple": {
            "format": "{levelname} {asctime} {module} {funcName} {lineno} {module} {process:d} {thread:d} {message}",
            "style": "{",
        },
    },
    "filters": {
        # "special": {
        #     "()": "project.logging.SpecialFilter",
        #     "foo": "bar",
        # },
        "require_debug_true": {
            "()": "django.utils.log.RequireDebugTrue",
        },
    },
    "handlers": {
        'null': {
            'level': 'DEBUG',
            'class': 'logging.NullHandler',
        },
        "console": {
            "level": "DEBUG",
            "filters": ["require_debug_true"],
            "class": "logging.StreamHandler",
            "formatter": "verbose",
        },
        "info": {
            "level": "INFO",
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': './app/storages/logs/app-' + datetime.datetime.now().strftime ("%Y-%m-%d") + '.log',
            'maxBytes': 300 * 1024 * 1024, # 300M Size
            'backupCount': 10,
            "formatter": "verbose",
            "encoding": "utf-8",
        },
        "error": {
            "level": "ERROR",
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': './app/storages/logs/app-' + datetime.datetime.now().strftime ("%Y-%m-%d") + '.log',
            'maxBytes': 300 * 1024 * 1024, # 300M Size
            'backupCount': 10,
            "formatter": "verbose",
            "encoding": "utf-8",
        },
    },
    "loggers": {
        "django": {
            "handlers": ['null'],
            'level': 'DEBUG',
            'propagate': False,
        },
        "log": {
            "handlers": ["console", 'info', 'error'],
            "propagate": True,
            'level': 'INFO',
        },
        # "django.request": {
        #     "handlers": ["console"],
        #     "level": "ERROR",
        #     "propagate": False,
        # },
        # "myproject.custom": {
        #     "handlers": ["console", "mail_admins"],
        #     "level": "INFO",
        #     "filters": ["special"],
        # },
    },
}

Sử dụng, tạo LogService

import logging

class LogService:

    ## 
    # log info
    # Author HaoDT
    ##
    @staticmethod
    def info(message = ''):
        logger = logging.getLogger('log')
        logger.info(message)

    ## 
    # log error
    # Author HaoDT
    ##
    @staticmethod
    def error(message = ''):
        logger = logging.getLogger('log')
        logger.error(message)
# Sử dụng
from app.services.LogService import LogService
  
LogService.error(str(e))

9. env

Sử dụng thư viện python-dotenv

// cài đặt
pip install python-dotenv

Tạo file .env cùng cấp với file manage.py

Ví dụ tôi định nghĩa 2 biến: DEBUG và DB_CONNECTION

DEBUG=True
DB_CONNECTION=django.db.backends.mysql
// sử dụng
import os
from dotenv import load_dotenv
  
load_dotenv()
  
os.getenv('DEBUG')
os.getenv('DB_CONNECTION')

11. Queue/Jobs

Django không có job/queue như Laravel (à mà hình như có Django-q). Nhưng nó có multi thread, có thể thực hiện tách 2 tác vụ như queue.

Định nghĩa thread class

import threading
from app.services.MailService import MailService

class SendMailJob(threading.Thread):
    dataSendmail = {
        'subject': '',
        'message': '', 
        'listEmail': []
    }
    def __init__(self, dataSendmail):
        self.dataSendmail = dataSendmail
        threading.Thread.__init__(self)
    
    def run(self):
        MailService.send(
            self.dataSendmail['subject'], 
            self.dataSendmail['message'], 
            self.dataSendmail['listEmail']
        )

Sử dụng: Truyền param và gọi hàm start()

...
from app.jobs.SendMailJob import SendMailJob

class TodoController(View):
    ## 
    # get
    # Author HaoDT
    ##
    def get(self, request):
        try:
            SendMailJob({ 
                'subject': 'Subject', 
                'message': 'Body', 
                'listEmail': ['tronghaomaico@gmail.com']
            }).start()
            dataTodo = TodoRepository.all()
            return ApiService.jsonData(dataTodo, _('messages.ok'))
        except Exception as e:
            LogService.error(str(e))
            return ApiService.jsonError(_('errors.default_error'))

10. Models

# get all
def all():
        try:
            dataTodo = Todo.objects.all()
            serializer = TodoSerializer(dataTodo, many=True)
            return serializer.data
        except Exception as e:
            LogService.error(str(e))
            return {}
# Create
def create(data):
        try:
            item = Todo()
            item.title = data['title']
            item.status = 0
            item.date = Helper.getTimeNow()
            item.save()
            return True
        except Exception as e:
            LogService.error(str(e))
            return False
# Update
def update(data):
        try:
            item = Todo.objects.get(id = data.get('id'))
            if item:
                if data.get('title'):
                    item.title = data.get('title')
                if data.get('status') or data.get('status') == 0:
                    item.status = data.get('status')
                item.save()
            return True
        except Exception as e:
            LogService.error(str(e))
            return False
# delete
def delete(data):
        try:
            item = Todo.objects.get(id = data.get('id'))
            if item:
                item.delete()
            return True
        except Exception as e:
            LogService.error(str(e))
            return False

11. Template

{% load static %}

{% if error %}
	<div>{{ error }}</div>
{% endif %}

<a href="{% url 'django_auth_adfs:login' %}"><button type="button">Login by AD</button></a>
  
<form method="post" action="{% url 'user.login' %}">
        {% csrf_token %}
        Username: <input type="type" name="username" value="" />
        Password: <input type="password" name="password" value="" />
        <input type="checkbox" name="remember_me" />Remember me
        <button type="submit">Login</button>
        <a href="{% url 'django_auth_adfs:login' %}"><button type="button">Login by AD</button></a>
</form>
// layout
{% block title %}{% endblock title %}

{% extends '../layout/index.html' %} 
{% block title %} INSPINIA | Dashboard v.2{% endblock %}
// import css, js
{% load static %}

 <link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet">
 <link href="{% static 'font-awesome/css/font-awesome.css' %}" rel="stylesheet">
 <script src="{% static 'js/jquery-3.1.1.min.js' %}"></script>
{% include '../__partials/side-menu.html' %}
// xài biến
{{ SITE_TITLE }}

12. Kinh nghiệm khác

12.1 Login Microsoft Entry

Tạo app và secret:

Làm theo tài liệu này: https://django-auth-adfs.readthedocs.io/en/latest/azure_ad_config_guide.html

Tạo app

Nhập các thông tin. Lưu ý nhập redirect URI: http://localhost:8000/oauth2/callback

Sau khi tạo bạn sẽ có thông tin. Lưu lại 2 thông tin để dùng cho ứng dụng:

+ Application (client) ID

+ Directory (tenant) ID

Tiếp theo tạo secret.

Copy value trên để sử dụng cho ứng dụng.

================================================================

Xử lý login microsoft bằng Django

Làm theo tài liệu này: https://django-auth-adfs.readthedocs.io/en/latest/install.html

Install django-auth-adfs

pip install django-auth-adfs

add setting.py

AUTHENTICATION_BACKENDS = (
    'django_auth_adfs.backend.AdfsAuthCodeBackend',
)

LOGIN_URL = "django_auth_adfs:login"
LOGIN_REDIRECT_URL = config('LOGIN_REDIRECT_URL')

# Client secret is not public information. Should store it as an environment variable.
client_id = config('CLIENT_ID')
client_secret = config('CLIENT_SECRET')
tenant_id = config('TENANT_ID')


AUTH_ADFS = {
    'AUDIENCE': client_id,
    'CLIENT_ID': client_id,
    'CLIENT_SECRET': client_secret,
    'CLAIM_MAPPING': {'first_name': 'given_name',
                      'last_name': 'family_name',
                      'email': 'upn'},
    'GROUPS_CLAIM': 'roles',
    'MIRROR_GROUPS': True,
    'USERNAME_CLAIM': 'upn',
    'TENANT_ID': tenant_id,
    'RELYING_PARTY_ID': client_id,
}

add env

CLIENT_ID=xxx
CLIENT_SECRET=yyy
TENANT_ID=zzz
LOGIN_REDIRECT_URL=/be/login/microsoft
  • CLIENT_ID: là Application (client) ID trong App registrations
  • TENANT_ID: là Directory (tenant) ID trong App registrations
  • CLIENT_SECRET: là secret trong certificate & secret
  • LOGIN_REDIRECT_URL: là url sau khi login success sẽ redirect đến có dữ liệu user

add route

urlpatterns = [
    ...
    path('oauth2/', include('django_auth_adfs.urls')),
]
  • Đường dẫn vào trang login microsoft sẽ là: oauth2/login
  • Đường dẫn callback là: oatuh2/callback
  • Đường dẫn callback sẽ đăng ký trên App registrations: http://localhost:8000/oauth2/callback

add install app

INSTALLED_APPS = [
    ...
    'django_auth_adfs',
]

add middleware

MIDDLEWARE = [
    ...
    'django_auth_adfs.middleware.LoginRequiredMiddleware',
]

Tạo url để redirect khi success

urlpatterns = [
    path("be/login/microsoft", views.MicrosoftEntryView.handleAfterLogin, name="microsoftEntry.afterLogin"),
]

Hàm xử lý

def handleAfterLogin(request):
        try:
            if (request.user):
                userMicrosoftEntry = {
                    'id': request.user.id,
                    'username': request.user.username,
                    'lastName': request.user.last_name,
                    'firstName': request.user.first_name,
                }
                print(userMicrosoftEntry)
        except Exception as e:
            # handle log

No related posts.

Post navigation

Previous Post:

Sử dụng google sheet làm database

Next Post:

Setting sendmail SES – Cloudformation

Trả lời Hủy

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

Ẩn sidebar

Tìm kiếm

Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages

Blog Công Nghệ

Bài viết mới

  • Master typescript
  • Sendmail trong Laravel sử dụng dịch vụ SES, SQS của Amazon
  • Install SSL in Nginx Ubuntu
  • Docker study
  • Bảo vệ: Hướng dẫn code bot Telegram easy game

Lượng truy cập

0074710
Visit Today : 306
Visit Yesterday : 178
This Month : 981
Who's Online : 1
© 2025 Blog Công Nghệ | WordPress Theme by Superbthemes