Photoshopで「不添加任何内容」「请直接喝酒」を入力したい。

「小塚ゴシック」で入力しようとすると文字化けする。
「hiragino sans cns」(繁体字中国語)に変更する

中国でどのフォントが人気なのかは良くわからんが。。
随机应变 ABCD: Always Be Coding and … : хороший
Photoshopで「不添加任何内容」「请直接喝酒」を入力したい。

「小塚ゴシック」で入力しようとすると文字化けする。
「hiragino sans cns」(繁体字中国語)に変更する

中国でどのフォントが人気なのかは良くわからんが。。
pcの時はrow(横並び)にして、改行してspの時はmargin-topをつける
.mt-3 と .mt-md-0 をつければ、mtを切り分けられる。
<div class="row mt-3"> <form class="d-flex col-md-4"> <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"> <button class="btn btn-outline-success" type="submit">Search</button> </form> <div class="col-md-3 mt-md-0 mt-3"> <select class="form-select" aria-label="Default"> <option selected>Recomend</option> <option value="1">Low Price</option> <option value="2">High Price</option> </select> </div> </div>
pc

sp

よっしゃーーー〜ーーー
<footer class="footer mt-4 py-3 bg-light">
<div class="container text-center">
<span class="text-muted">Demo Company © All Right Reserved.</span>
</div>
</footer>


2行にしたい。
<footer class="footer mt-4 py-3 bg-light">
<div class="text-end">
<a href="">Privacy Policy</a> <a href="">Terms</a>
</div>
<div class="text-center">
<span class="text-muted">Demo co., © All Right Reserved.</span>
</div>
</footer>
### jpeg写真を用意する

### 文字を追加する
Photoshopで画像を開いて、sideメニューのテキストから文字を追加する

### 長方形に画像を切り抜く
長方形選択ツールで画像をくり抜いて、「イメージ」->「切り抜く」で画像をくり抜く


### アスペクト比を指定して切り抜く
黄金比などありますが、今回は縦横比を1:2で切り抜きたいと思います。
headerメニュー「スタイル」で「縦横比を固定」を選択し、幅2、高さ1指定にします。
サイズは 1280 x 640 になっています。

web用に保存で jpegで保存します。

ちょっと2:1だとPCで見たときに縦長すぎるので、2:0.75に変更する


うーん、難しい
logoは .navbar-brand、右寄せは .float-end を使用する。
参考: 横の配置ユーティリティ
<nav class="navbar navbar-light bg-light"> <div class="container-fluid"> <a class="navbar-brand">Demo EDI Manager</a> <div class="float-end"> hoge </div> </div> </nav>

<nav class="navbar navbar-light bg-light"> <div class="container-fluid"> <a class="navbar-brand">Demo EDI Manager</a> <div class="float-end"> <ul class="list-group list-group-horizontal"> <li class="list-group-item">Order</li> <li class="list-group-item">Logout</li> </ul> </div> </div> </nav>

### レスポンシブル対応
<nav class="navbar navbar-light navbar-expand-md bg-light">
<a class="navbar-brand">Demo</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#responsiveMenu" aria-controls="responsiveMenu" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="responsiveMenu">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<a class="nav-link" href="#">Order</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Logout</a>
</li>
</ul>
</div>
</nav>
pc

sp

ん? レスポンシブルでコーディングすると、responsiveMenuのli要素に対して .float-endが効かないように見えるがどうしたら良いんだ?
### justify-content-end
.float-end ではなく .justify-content-end にすると、PC版は右寄せになる。
<div class="collapse navbar-collapse justify-content-end" id="responsiveMenu">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<a class="nav-link" href="#">Order</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Logout</a>
</li>
</ul>
</div>

なるほどー
fontawesomeを使って、アイコンを装飾します。

ほう、良い感じ。
Github: https://github.com/themesberg/volt-bootstrap-5-dashboard
Fileをvagrantにダウンロードし、Quick Startに沿って構築していきます。
$ tree
97 directories, 2216 files
// npmでgulpをインストールします
$ npm install gulp-cli -g
$ npm install
// node_modulesがインストールされました
$ ls
LICENSE.md README.md gulpfile.js html&css node_modules package-lock.json package.json src
// サーバ起動
$ gulp
http://192.168.33.10:3000/index.html
// ポートが3000番になっている事に留意

コマンドラインでhtml&cssのフォルダに移動するには、&の前にバックスラッシュをつける
$ cd html\&css

これからdashboard中心に編集していきます。
### CSVファイルを作成
アナと雪の女王,,,1,名詞,一般,*,*,*,*,アナと雪の女王,アナトユキノジョオウ,アナトユキノジョオー

辞書のフォーマット: 表層形,左文脈ID,右文脈ID,コスト,品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用型,活用形,原型,読み,発音
$ sudo mkdir /usr/local/lib/mecab/dic/userdic
$ sudo sudo /usr/lib/mecab/mecab-dict-index \
> -d /usr/local/mecab/dic/ipadic \
> -u /usr/local/lib/mecab/dic/userdic/add.dic \
> -f utf-8 \
> -t utf-8 \
> add_term.csv
dictionary_compiler.cpp(82) [param.load(DCONF(DICRC))] no such file or directory: /usr/local/mecab/dic/ipadic/dicrc
うーん、全然上手くいかんな。。
### mecabインストール
$ sudo yum update -y
$ sudo yum groupinstall -y “Development Tools”
$ wget ‘https://drive.google.com/uc?export=download&id=0B4y35FiV1wh7cENtOXlicTFaRUE’ -O mecab-0.996.tar.gz
$ tar xzf mecab-0.996.tar.gz
$ cd mecab-0.996
$ ./configure
$ make
$ make check
$ sudo make install
$ cd –
$ rm -rf mecab-0.996*
$ git clone –depth 1 https://github.com/neologd/mecab-ipadic-neologd.git
$ ./mecab-ipadic-neologd/bin/install-mecab-ipadic-neologd -n -a -y
terminate called after throwing an instance of ‘std::bad_alloc’
what(): std::bad_alloc
$ sudo /bin/dd if=/dev/zero of=/var/swap.1 bs=1M count=1024
$ sudo /sbin/mkswap /var/swap.1
$ sudo /sbin/swapon /var/swap.1
$ free
what(): std::bad_alloc
VMのmemoryを4Gにしないと駄目らしい。
面倒なので、focalfossaで開発する
$ sudo apt install mecab
$ sudo apt install libmecab-dev
$ sudo apt install mecab-ipadic-utf8
$ mecab
特急はくたか
特急 名詞,一般,*,*,*,*,特急,トッキュウ,トッキュー
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
く 動詞,自立,*,*,カ変・クル,体言接続特殊2,くる,ク,ク
た 助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
か 助詞,副助詞/並立助詞/終助詞,*,*,*,*,か,カ,カ
EOS
$ git clone https://github.com/neologd/mecab-ipadic-neologd.git
$ cd mecab-ipadic-neologd
$ sudo bin/install-mecab-ipadic-neologd
$ sudo vi /etc/mecabrc
;dicdir = /var/lib/mecab/dic/debian dicdir = /usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd
なんかneologdのインストールが上手くいかんな。。。
いよいよショッピングカートを作っていきます。
$ python3 manage.py startapp cart
setting.py
INSTALLED_APPS = [
'shop',
'search',
'cart',
// 省略
]
// 省略
'DIRS': [os.path.join(BASE_DIR, 'shop', 'templates/'), os.path.join(BASE_DIR, 'search', 'templates/'), os.path.join(BASE_DIR, 'cart', 'templates/')],
cart/models.py
from django.db import models from shop.models import Product class Cart(models.Model): cart_id = models.CharField(max_length=250, blank=True) date_added = models.DateField(auto_now_add=True) class Meta: db_table = 'Cart' ordering = ['date_added'] def __str__(self): return self.cart_id class CartItem(models.Model): product = models.ForeignKey(Product, on_delete=models.CASCADE) cart = models.ForeignKey(Cart, on_delete=models.CASCADE) quantity = models.IntegerField() active = models.BooleanField(default=True) class Meta: db_table = 'CartItem' def sub_total(self): return self.product.price * self.quantity def __str__(self): return self.product.name
$ python3 manage.py makemigrations cart
$ python3 manage.py migrate
cart/urls.py
from django.urls import path
from . import views
app_name = 'cart'
urlpatterns = [
path('', views.cart_detail, name='cart_detail'),
]
urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('shop/', include('shop.urls')),
path('search/', include('search.urls')),
path('cart/', include('cart.urls')),
]
cart/views.py
L session.session_keyでセッションの値を取得する
from django.shortcuts import render, redirect from .models import Cart, CartItem from django.core.exceptions import ObjectDoesNotExist def _cart_id(request): cart = request.session.session_key if not cart: cart = request.session.create() return cart def cart_detail(request, total=0, counter=0, cart_items = None): try: cart = Cart.objects.get(cart_id=_cart_id(request)) cart_items = CartItem.objects.filter(cart=cart, active=True) for cart_item in cart_items: total += (cart_item.product.price * cart_item.quantity) counter += cart_item.quantity except ObjectDoesNotExist: pass return render(request, 'cart/cart.html', dict(cart_items = cart_items, total = total, counter = counter))
cart/template/cart/cart.html
{% extends "base.html" %}
{% load static %}
{% block metadescription %}
This is the shopping cart page.. Proceed to review your items and place the order.
{% endblock %}
{% block title %}
Cart - Various Product Store
{% endblock %}
{% block content %}
{% if not cart_items %}
<div>
<div class="text-center">
<br>
<h1 class="text center my_title">Your shopping cart is empty</h1>
<br>
<p class="text-center">
Please click <a href="{% url 'shop:all_product' %}">here</a> to continue shopping.
</p>
</div>
</div>
{% else %}
<div>
<div class="text-center">
<br>
<h1 class="text-center my_title">
Your shopping cart
</h1>
</div>
<br>
</div>
<div class="row mx-auto">
<div class="col-12 col-sm-12 col-lg-6 text-center">
<table class="table my_custom_table">
<thread class="my_custom_thread">
<tr>
<th colspan="5">
Your items
</th>
</tr>
</thread>
<tbody>
{% for cart_item in cart_items %}
<tr>
<td><a href="cart_item.product.get_absolute_url"><img src="{{cart_item.product.image.url}}" alt="" class="float-left rounded custom_image"></a></td>
<td class="text-left">
{{cart_item.product.name}}
<br>
SKU: {{cart_item.product.id}}
<br>
Unit Price: ${{cart_item.product.price}}
<br>
Qty: {{cart_item.quantity}} x ${{cart_item.product.price}}
</td>
<td>
${{cart_item.sub_total}}
</td>
{% if cart_item.quantity < cart_item.product.stock %}
<td>
<a href="{% url 'cart:add_cart' cart_item.product.id %}" class="custom_a"><i class="fas fa-plus-circle custom_icon"></i></a>
<a href="" class="custom_a"><i class="fas fa-minus-circle custom_icon"></a>
<a href="" class="custom_item"><i class="far fa-trash-alt"></a>
</td>
{% else %}
<td>
<a href="" class="custom_a"><i class="fas fa-minus-circle custom_icon"></a>
<a href="" class="custom_item"><i class="far fa-trash-alt"></i></a>
</td>
<td></td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="col-12 col-sm-12 col-lg-6 text-center">
<table class="table my_custom_table">
<thread class="my_custom_thead">
<tr>
<th>
Checkout
</th>
</tr>
</thread>
<tbody>
<tr>
<td>
Please review your shopping cart item before proceeding with the order payment.
</td>
</tr>
<tr>
<td class="text-left">
Your total is: <strong>${{total}}</strong>
</td>
</tr>
</tbody>
</table>
<div class="mx-auto">
<a href="{% url 'shop:all_product' %}" class="btn-secondary btn-block my_custom_button">Continue Shopping</a>
</div>
</div>
</div>
{% endif %}
{% endblock %}

models.py
from shop.models import Product
def add_cart(request, Product_id):
product = Product.objects.get(id=product_id)
try:
cart = Cart.objects.get(cart_id=_cart_id(request))
except Cart.DoesNotExist:
cart = Cart.objects.create(
cart_id = _cart_id(request)
)
cart.save()
try:
cart_item = CartItem.objects.get(product=product, cart=cart)
cart_item.quantity += 1
cart_item.save()
except CartItem.DoesNotExist:
cart_item = CartItem.objects.create(
product = product,
quantity = 1,
cart = cart
)
cart_item.save()
return redirect('cart:cart_detail')
urls.py
urlpatterns = [
path('add/<int:product_id>/', views.add_cart, name='add_cart'),
path('', views.cart_detail, name='cart_detail'),
]
product_detail.html
<a class="btn btn-secondary" href="{% url 'cart:add_cart' product.id %}">Add to Cart</a>

cart/views.py
def cart_remove(request, product_id):
cart = Cart.objects.get(cart_id=_cart_id(request))
product = get_object_or_404(Product, id=product_id)
cart_item = CartItem.objects.get(product=product, cart=cart)
if cart_item.quantity > 1:
cart_item.quantity -= 1
cart_item.save()
else:
cart_item.delete()
return redirect('cart:cart_detail')
def full_remove(request, product_id):
cart = Cart.objects.get(cart_id=_cart_id(request))
product = get_object_or_404(Product, id=product_id)
cart_item = CartItem.objects.get(product=product, cart=cart)
cart_item.delete()
return redirect('cart:cart_detail')
urls.py
app_name = 'cart'
urlpatterns = [
path('add/<int:product_id>/', views.add_cart, name='add_cart'),
path('', views.cart_detail, name='cart_detail'),
path('remove/<int:product_id>/', views.cart_remove, name='cart_remove'),
path('full_remove/<int:product_id>/', views.full_remove, name='full_remove')
]
cart/context_processors.py
from .models import Cart, CartItem
from .views import _cart_id
def counter(request):
item_count = 0
if 'admin' in request.path:
return {}
else:
try:
cart = Cart.objects.filter(cart_id=_cart_id(request))
cart_items = CartItem.objects.all().filter(cart=cart[:1])
for cart_item in cart_items:
item_count += cart_item.quantity
except Cart.DoesNotExist:
item_count = 0
return dict(item_count = item_count)
settings.py
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'cart.context_processors.counter',
],
navbar.html
{% if item_count > 0 %}
<li class="nav-item">
<a class="nav-link" href="{% url 'cart:cart_detail' %}">({{item_count}})</a>
</li>
{% endif %}
cart.html
{% if cart_item.quantity < cart_item.product.stock %}
<td>
<a href="{% url 'cart:add_cart' cart_item.product.id %}" class="custom_a"><i class="fas fa-plus-circle custom_icon"></i></a>
<a href="{% url 'cart:cart_remove' cart_item.product.id %}" class="custom_a"><i class="fas fa-minus-circle custom_icon"></a>
<a href="{% url 'cart:full_remove' cart_item.product.id %}" class="custom_item"><i class="far fa-trash-alt"></a>
</td>
{% else %}
<td>
<a href="{% url 'cart:cart_remove' cart_item.product.id %}" class="custom_a"><i class="fas fa-minus-circle custom_icon"></a>
<a href="{% url 'cart:full_remove' cart_item.product.id %}" class="custom_item"><i class="far fa-trash-alt"></i></a>
</td>
<td></td>
{% endif %}

なるほど、ただこれだと、ログアウトした時の処理などが入ってないから、完成には遠いな。Libraryはないのかしら?
### search app作成
$ python3 manage.py startapp search
setting.py
INSTALLED_APPS = [
'shop',
'search',
// 省略
]
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'shop', 'templates/'), os.path.join(BASE_DIR, 'search', 'templates/')],
// 省略
},
]
search/urls.py
from django.urls import path
from . import views
app_name = 'search'
urlpatterns = [
path('', views.search_result, name='search_result'),
]
urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('shop/', include('shop.urls')),
path('search/', include('search.urls')),
]
search/views.py
from django.shortcuts import render
from shop.models import Product
def search_result(request):
products = Product.objects.all()
return render(request, 'search.html', {'products': products})
navbar.html
<form class="form-inline my-2 my-lg-0" action="{% url 'search:search_result' %}" method="get">
<input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search" name="q">
<button class="btn btn-secondary my-2 my-sm-0" type="submit"><i class="fas fa-search"></i></button>
</form>
search.html
{% extends "base.html" %}
{% load static %}
{% block metadescription %}
We have a variety of stunning and comfy cushions. Lock for the one that suits your needs.
{% endblock %}
{% block title %}
Search - Perfect Cushion Store
{% endblock %}
{% block content %}
<div>
<p class="text-center my_search_text">You have searched for: <b>"{{ query }}"</b></p>
</div>
<div class="container">
<div class="row mx-auto">
{% for product in products %}
<div class="my_bottom_margin col-9 col-sm-12 com-md-4 com-md-12 col-lg-4">
<div class="card text-center" style="min-width: 18rem;">
<a href="{{product.get_url}}"><img class="card-img-top my_image" src="{{product.image.url}}" alt="{{product.name}}"></a>
<div class="card-body">
<h4>{{product.name}}</h4>
<p>${{product.price}}</p>
</div>
</div>
</div>
{% empty %}
<div class="row mx-auto">
<p class="text-center my_search_text">0 results found.</p>
</div>
{% endfor %}
</div>
</div>
{% endblock %}

OKでしょう。