---
# System prepended metadata

title: Notes for Django
tags: [thesis, django, jptw, technology, python]

---

###### tags: `jptw` `thesis` `technology` `python` `django`
# Notes for Django
> Tutorial:
> [1] [Python 3 Tutorial 第八堂（2）建立 App 與模型](https://openhome.cc/Gossip/CodeData/PythonTutorial/AppModelPy3.html)

## Folder Structure
```
mysite
├── manage.py
├── /mysite
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   ├── asgi.py
│   └── wsgi.py
└── /polls
    ├── __init__.py
    ├── admin.py
    ├── apps.py
    ├── migrations/
    │   └── __init__.py
    ├── models.py
    ├── tests.py
    └── views.py
```

## Setup Django Project
### Install
```shell
$ pip3 install Django
```

### Start Project
```shell
// create
$ django-admin startproject mysite

// run
$ python manage.py runserver
```

### Create App
```shell
$ python manage.py startapp polls
```

> Tutorial:
> [1] [编写你的第一个 Django 应用，第 1 部分](https://docs.djangoproject.com/zh-hans/3.1/intro/tutorial01/)


## Models

### on_delete
`models.CASCADE` 對應資料一併刪除

> Ref: [Day6 : 資料庫的創建 - Models](https://ithelp.ithome.com.tw/articles/10200181)

### unique_together
Multiple fields as unique key

```python
from django.db import models

class Post(models.Model):
    user= models.ForeignKey(User)
    title= models.ForeignKey(Post)
    date= models.DateTimeField(auto_now= True)
    
    def __str__(self):
        return str(self.user) + ':' + str(self.post)

    class Meta:
       unique_together = ("user", "title")

```

> Ref: [How to Make Fields of a Database Table Unique Together in Django](http://www.learningaboutelectronics.com/Articles/How-to-make-fields-of-a-database-table-unique-together-in-Django.php)


### Filter
```python
from operator import and_
from django.db.models import Q

categories = ['holiday', 'summer']

# Method 1
res = Photo.filter(reduce(and_, [Q(tags__name=c) for c in categories]))

# Method 2
res = Photo.filter(Q(tags__name='holiday') & Q(tags__name='summer'))
```

> Ref: [Django filter queryset __in for *every* item in list](https://www.semicolonworld.com/question/43842/django-filter-queryset-in-for-every-item-in-list)


### Serializer
```python
from rest_framework import serializers

serializer = PostSerializer(data=data)
serializer.is_valid()
```

> Ref: [Django REST Framework | Serializers](https://www.django-rest-framework.org/api-guide/serializers/)


## Command
### Structure
```
polls/
    __init__.py
    models.py
    management/
        commands/
            _private.py
            closepoll.py
    tests.py
    views.py
```

### HowToUse
closepoll.py
```python
from django.core.management.base import BaseCommand, CommandError
from polls.models import Question as Poll

class Command(BaseCommand):
    help = 'Closes the specified poll for voting'

    def add_arguments(self, parser):
        parser.add_argument('poll_ids', nargs='+', type=int)

    def handle(self, *args, **options):
        ...
        self.stdout.write(self.style.SUCCESS('Successfully closed poll "%s"' % poll_id))
```
Terminal
```shell
$ python manage.py closepoll <poll_id>
```

> Tutorial:
> [1] [编写自定义 django-admin 命令](https://docs.djangoproject.com/zh-hans/3.1/howto/custom-management-commands/)
> [2]* [How to Create Custom Django Management Commands](https://simpleisbetterthancomplex.com/tutorial/2018/08/27/how-to-create-custom-django-management-commands.html)
> [3] [django-admin and manage.py](https://docs.djangoproject.com/en/3.0/ref/django-admin/)


## Settings
### Environment
Installation
```cmd
$ pip install django-environ
```
`.env` file
```python
DEBUG=FALSE
SECRET_KEY=your-secret-key
DATABASE_URL=psql://urser:un-githubbedpassword@127.0.0.1:8458/database
SQLITE_URL=sqlite:///my-local-sqlite.db
CACHE_URL=memcache://127.0.0.1:11211,127.0.0.1:11212,127.0.0.1:11213
REDIS_URL=rediscache://127.0.0.1:6379/1?client_class=django_redis.client.DefaultClient&password=ungithubbed-secret
```

> Ref: [Welcome to Django-environ’s documentation!](https://django-environ.readthedocs.io/en/latest/)

### Database
```python
DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'OPTIONS': {'charset': 'utf8mb4'},
            (...)
```

SQL command
```mysql
ALTER DATABASE el CHARACTER SET utf8 COLLATE utf8_general_ci
```
`.env` file
```python
DATABASE_URL = mysql://user:pass@localhost/django?CHARSET=utf8mb4
```

> Ref: 
> [1] [Make MySQL backend default to utf8mb4 encoding](https://code.djangoproject.com/ticket/18392)
> [2] [Checks | Django-MySQL](https://django-mysql.readthedocs.io/en/latest/checks.html#django-mysql-w003-utf8mb4)
> [3] [Collation and charset?](https://github.com/joke2k/django-environ/issues/96)

### CORS
```python
INSTALLED_APPS = [
    ...
    'corsheaders',
    ...
]

MIDDLEWARE = [
    ...
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    ...
]

CORS_ALLOW_METHODS = [
    'DELETE',
    'GET',
    'OPTIONS',
    'PATCH',
    'POST',
    'PUT',
]

CCORS_ALLOWED_ORIGINS = [
    "https://example.com",
    "https://sub.example.com",
    "http://localhost:8080",
    "http://127.0.0.1:9000"
]
```
> Ref:[django-cors-headers 3.5.0](https://pypi.org/project/django-cors-headers/)


## Database
> Ref: [Notes for Database | Cosine](/@ahglab/thesis-tech-db)

## Routers
```python
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from main import views

router - DefaultRouter()
router.register(r'main', views.mainViewSet)

urlpatterns = [
    path('', include(router.urls)),
]
```

> Ref: [Tutorial 6: ViewSets & Routers](https://www.django-rest-framework.org/tutorial/6-viewsets-and-routers/)