Djnago memo

◾️ null=True VS blank=True

blank¶
Field.blank¶
If True, the field is allowed to be blank. Default is False.

Note that this is different than null. null is purely database-related, whereas blank is validation-related. If a field has blank=True, form validation will allow entry of an empty value. If a field has blank=False, the field will be required.

  • User model
avatar = models.ImageField(blank=True)
gender = models.CharField(choices=GENDER_CHOICES, max_length=10, blank=True)
bio = models.TextField(default="", blank=True)
birthday = models.DateField(blank=True, null=True)
language = models.CharField(choices=LANG_CHOICES, max_length=2, blank=True)
currency = models.CharField(choices=CURRENCY_CHOICES, max_length=3, blank=True)
superhost = models.BooleanField(default=False)
  • Created user table

-> only blank=True option not allow Null : “avatar” varchar(100) NOT NULL

sqlite> .schema users_user
CREATE TABLE IF NOT EXISTS "users_user" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "password" varchar(128) NOT NULL, "last_login" datetime NULL, "is_superuser" bool NOT NULL, "username" varchar(150) NOT NULL UNIQUE, "first_name" varchar(30) NOT NULL, "last_name" varchar(150) NOT NULL, "email" varchar(254) NOT NULL, "is_staff" bool NOT NULL, "is_active" bool NOT NULL, "date_joined" datetime NOT NULL, "avatar" varchar(100) NOT NULL, "gender" varchar(10) NOT NULL, "bio" text NOT NULL, "birthday" date NULL, "language" varchar(2) NOT NULL, "currency" varchar(3) NOT NULL, "superhost" bool NOT NULL);

◾️ abstract time stamp field

<class Meta: abstract = True> do not create table

<auto_now_add=True> Auto Model Created Time

<auto_now=True> Auto Model Updated Time

from django.db import models


# Create your models here.
class AbstractTimeStampModel(models.Model):
    """ Time Stamped Model """

    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True
  • usage of abstract time stamp
from django.db import models
from core import models as core_models


# Create your models here.
class Room(core_models.AbstractTimeStampModel):
    """ Room Model Definition """

    name = models.CharField(max_length=140)

◾️ third-party countries field

  • settings.py
THIRD_PARTY_APPS = ["django_countries"]
  • usage

header import(このような順番で定義すると分かりやすい)

python > django > third party > user defined
from django.db import models
from django_countries.fields import CountryField
from core import models as core_models


# Create your models here.
class Room(core_models.AbstractTimeStampModel):
    """ Room Model Definition """

    # https://github.com/SmileyChris/django-countries
    country = CountryField()

◾️ foreigin key

  • rooms model : Many(rooms) to One(user) relation
from django.db import models
from django_countries.fields import CountryField
from core import models as core_models
from users import models as user_models


# Create your models here.
class Room(core_models.AbstractTimeStampModel):
    """ Room Model Definition """
    name = models.CharField(max_length=140)
    ........
    instant_book = models.BooleanField(default=False)
    host = models.ForeignKey(user_models.User, on_delete=models.CASCADE)
  • created rooms
sqlite> .schema rooms_room
CREATE TABLE IF NOT EXISTS "rooms_room" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "created" datetime NOT NULL, "updated" datetime NOT NULL, "name" varchar(140) NOT NULL, "description" text NOT NULL, "country" varchar(2) NOT NULL, "city" varchar(80) NOT NULL, "price" integer NOT NULL, "address" varchar(140) NOT NULL, "guests" integer NOT NULL, "beds" integer NOT NULL, "bedrooms" integer NOT NULL, "baths" integer NOT NULL, "check_in" time NOT NULL, "check_out" time NOT NULL, "instant_book" bool NOT NULL
, "host_id" integer NOT NULL REFERENCES "users_user" ("id") DEFERRABLE INITIALLY DEFERRED); CREATE INDEX "rooms_room_host_id_7f45f18c" ON "rooms_room" ("host_id");
sqlite> 

◾️ paintjs for web draw

◾️ One to Many relation Many to Many relation

  • rooms have only one user ( many to one )
  • rooms have many room type ( many to many)
from django.db import models
from django_countries.fields import CountryField
from core import models as core_models
from users import models as user_models


# Create your models here.
class AbstractItem(core_models.AbstractTimeStampModel):
    """ Abstract Item """

    name = models.CharField(max_length=80)

    class Meta:
        abstract = True

    def __str__(self):
        return self.name


class RoomType(AbstractItem):

    pass


class Room(core_models.AbstractTimeStampModel):
    """ Room Model Definition """

    name = models.CharField(max_length=140)
    .......
    host = models.ForeignKey(user_models.User, on_delete=models.CASCADE)
    room_type = models.ManyToManyField(RoomType, blank=True)

    def __str__(self):
        return self.name
  • admin panel for Room and RoomType
from django.contrib import admin
from . import models


# Register your models here.
@admin.register(models.RoomType)
class ItemAdmin(admin.ModelAdmin):
    """ Custom Item Admin """

    pass


@admin.register(models.Room)
class RoomAdmin(admin.ModelAdmin):
    """ Custom Rooms Admin """

    pass
  • show admin
  • show created table
sqlite> .schema rooms_room
CREATE TABLE IF NOT EXISTS "rooms_room" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "created" datetime NOT NULL, "updated" datetime NOT NULL, "name" varchar(140) NOT NULL, "description" text NOT NULL, "country" varchar(2) NOT NULL, "city" varchar(80) NOT NULL, "price" integer NOT NULL, "address" varchar(140) NOT NULL, "guests" integer NOT NULL, "beds" integer NOT NULL, "bedrooms" integer NOT NULL, "baths" integer NOT NULL, "check_in" time NOT NULL, "check_out" time NOT NULL, "instant_book" bool NOT NULL, "host_id" integer NOT NULL REFERENCES "users_user" ("id") DEFERRABLE INITIALLY DEFERRED);
CREATE INDEX "rooms_room_host_id_7f45f18c" ON "rooms_room" ("host_id");

sqlite> .schema rooms_roomtype
CREATE TABLE IF NOT EXISTS "rooms_roomtype" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "created" datetime NOT NULL, "updated" datetime NOT NULL, "name" varchar(80) NOT NULL);

sqlite> .schema rooms_room_room_type
CREATE TABLE IF NOT EXISTS "rooms_room_room_type" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "room_id" integer NOT NULL REFERENCES "rooms_room" ("id") DEFERRABLE INITIALLY DEFERRED, "roomtype_id" integer NOT NULL REFERENCES "rooms_roomtype" ("id") DEFERRABLE INITIALLY DEFERRED);
CREATE UNIQUE INDEX "rooms_room_room_type_room_id_roomtype_id_7630b1fa_uniq" ON "rooms_room_room_type" ("room_id", "roomtype_id");
CREATE INDEX "rooms_room_room_type_room_id_1b3ad525" ON "rooms_room_room_type" ("room_id");
CREATE INDEX "rooms_room_room_type_roomtype_id_aae49861" ON "rooms_room_room_type" ("roomtype_id");

sqlite> select * from rooms_roomtype;
1|2021-04-14 14:26:33.297073|2021-04-14 14:26:33.297106|Hotel Room
2|2021-04-14 14:26:43.709087|2021-04-14 14:26:43.709118|Shared Room
3|2021-04-14 14:26:52.727383|2021-04-14 14:26:52.727432|Private Room
4|2021-04-14 14:27:02.231116|2021-04-14 14:27:02.231150|Entire Room

◾️ Register serveral model with one class for admin panel

  • define models
# Create your models here.
class AbstractItem(core_models.AbstractTimeStampModel):
    """ Abstract Item """

    name = models.CharField(max_length=80)

    class Meta:
        abstract = True

    def __str__(self):
        return self.name


class RoomType(AbstractItem):
    """ Ro0mType Model Definition """

    pass


class Amenity(AbstractItem):
    """ Amenity Model Definition """

    pass


class HouseRule(AbstractItem):
    """ HouseRule Model Definition """

    pass


class Facility(AbstractItem):
    """ Amenity Model Definition """

    pass
  • register RoomType and Amenity
# Register your models here.
@admin.register(models.RoomType, models.Facility, models.Amenity, models.HouseRule)
class ItemAdmin(admin.ModelAdmin):
    """ Custom Item Admin """

    pass
  • Check names on admin panel

-> we need to change the naming rule

  1. Ammenitys->Ammenities
  2. House rules->House Rules

◾️ Change naming rule of Admin panel

  • class meta for naming
class AbstractItem(core_models.AbstractTimeStampModel):
    """ Abstract Item """

    name = models.CharField(max_length=80)

    class Meta:
        abstract = True

    def __str__(self):
        return self.name


class RoomType(AbstractItem):
    """ Ro0mType Model Definition """

    class Meta:
        verbose_name = "Room Type"


class Amenity(AbstractItem):
    """ Amenity Model Definition """

    class Meta:
        verbose_name_plural = "Amenities"


class HouseRule(AbstractItem):
    """ HouseRule Model Definition """

    class Meta:
        verbose_name = "House Rule"


class Facility(AbstractItem):
    """ Amenity Model Definition """

    class Meta:
        verbose_name_plural = "Facilities"
  • check admin panel

◾️ ForeignKey : set model name as string

  1. models.ForeignKey(Room, on_delete=models.CASCADE): need to import model
  2. models.ForeignKey(“Room”, on_delete=models.CASCADE): Not need import model

◾️ related_name

-> If related_name is not exist, it cause Reverse accessor clash

class User(models.Model):
author = models.ForeignKey('category.Category', related_name='author_user')
editor = models.ForeignKey('category.Category', related_name='editor_user')

◾️ routing example

from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path("", include("core.urls", namespace="core")),
    path("movies", include("movies.urls", namespace="movies")),
    path("books", include("books.urls", namespace="books")),
    path("genres", include("categories.urls", namespace="genres")),
    path("people", include("people.urls", namespace="people")),
    path("admin/", admin.site.urls),
]


if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
from django.urls import path
from movies.views import resolve_movies

app_name="movies"

urlpatterns = [
  path("", resolve_movies, name="movies")
]
from django.shortcuts import render

def resolve_movies(request):
  return render(request, "movies.html")

◾️ limiting queryset

Generally, slicing a QuerySet returns a new QuerySet

This returns the sixth through tenth objects (OFFSET 5 LIMIT 5):
Entry.objects.all()[5:10]

◾️ check GET param

  • http://127.0.0.1:8000/?page=1&save=none
print(request.GET.keys())
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
dict_keys(['page', 'save'])
  • http://127.0.0.1
if page query is not exist, default page=0
print(request.GET.get("page", 0))
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
0
  • manual page

http://127.0.0.1:8000/?page=1

http://127.0.0.1:8000/?page=2

this code covers [http://127.0.0.1:8000/?page=]

def all_rooms(request):
    # print(dir(request.GET))
    page = request.GET.get("page", 1)
    page = int(page or 1)
    page_size = 10
    limit = page_size * page
    offset = limit - page_size
    all_rooms = models.Room.objects.all()[offset:limit]
    return render(request, "rooms/home.html", context={"rooms": all_rooms})

◾️template tags and filter

Adds the argument to the value.

For example:

{{ value|add:"2" }}

◾️queryset are lazy

this code do not fetch data immediately

room_list = models.Room.objects.all() -> not load data

-> if we code “print(room_list)”, this call fetch data from db

def all_rooms(request):
    # print(dir(request.GET))
    page = request.GET.get("page")
    room_list = models.Room.objects.all()
QuerySets are lazy – the act of creating a QuerySet doesn’t involve any database activity. You can stack filters together all day long, and Django won’t actually run the query until the QuerySet is evaluated. Take a look at this example:

◾️paginator

def all_rooms(request):
    # print(dir(request.GET))
    page = request.GET.get("page")
    room_list = models.Room.objects.all()
    paginator = Paginator(room_list, 10, orphans=5)
    rooms = paginator.get_page(page)
    #print(vars(rooms.paginator))
    return render(request, "rooms/home.html", {"page": rooms})
{% extends "base.html" %}

{% block page_name %}
    Room | airbnb
{% endblock page_name %}

{% block content %}
    {% for room in page.object_list %}
        <h2>{{room.name}} | ¥{{room.price}}</h2>
    {% endfor %}

    <h5>
    {% if page.has_previous %}
        <a href="?page={{page.number|add:-1}}"><</a>
    {% endif %}
    
    page {{page.number}} of {{page.paginator.num_pages}}
    
    {% if page.has_next %}
        <a href="?page={{page.number|add:1}}">></a>
    {% endif %}
    </h5>

    {% for p in page.paginator.page_range %}
        <a href="?page={{p}}">{{p}} </a>
    {% endfor %}
{% endblock %}

◾️paginator.get_page() or paginator.page()

paginator.page control more exception

def all_rooms(request):
    # print(dir(request.GET))
    page = request.GET.get("page", 1)
    room_list = models.Room.objects.all()
    paginator = Paginator(room_list, 10, orphans=5)

    try:
        rooms = paginator.page(int(page))
        return render(request, "rooms/home.html", {"page": rooms})
    except EmptyPage:
        return redirect("/")

◾️ reverse ex for url

from django.urls import reverse

....

def get_absolute_url(self):
        return reverse("rooms:detail", kwargs={"pk": self.pk})

def room_detail(request, pk):
    print(pk)
    try:
        room = models.Room.objects.get(pk=pk)
        return render(request, "rooms/detail.html", {"room": room})
    except models.Room.DoesNotExist:
        # return redirect("")
        return redirect(reverse("core:home"))

◾️ redirect or Http404

  1. use redirect home
from django.shortcuts import render, redirect
....
def room_detail(request, pk):
    print(pk)
    try:
        room = models.Room.objects.get(pk=pk)
        return render(request, "rooms/detail.html", {"room": room})
    except models.Room.DoesNotExist:
        # return redirect("")
        return redirect(reverse("core:home"))

2. use Http404 for request error

from django.http import Http404

def room_detail(request, pk):
    print(pk)
    try:
        room = models.Room.objects.get(pk=pk)
        return render(request, "rooms/detail.html", {"room": room})
    except models.Room.DoesNotExist:
        raise Http404()

3. use templates 404.html for Http404() exception

{% extends "base.html" %}

{% block page_name %}
    404 Error
{% endblock page_name %}

{% block content %}
    <h1>Not found request page</h1>
{% endblock %}

◾️FBV(Function based View) VS CBV(Class based View)

  1. FBV

templates/rooms/detail.html

app_name = "rooms"

urlpatterns = [
    path("<int:pk>", room_views.room_detail, name="detail"),
]
def room_detail(request, pk):
    print(pk)
    try:
        room = models.Room.objects.get(pk=pk)
        return render(request, "rooms/detail.html", {"room": room})
    except models.Room.DoesNotExist:
        raise Http404()

2. CBV

templates/rooms/room_detail.html

app_name = "rooms"

urlpatterns = [
    path("<int:pk>", room_views.room_detail.as_view(), name="detail"),
]
from django.views.generic import ListView, DetailView

class room_detail(DetailView):
    """ RoomDetail Definition """

    model = models.Room

◾️db search : field lookups

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です