https://www.pythoneatstail.com/en/overview-all-articles/set-allauth-django-project/

 

Set up authentication for a Python Django site - PythonEatsTail

With a few modifications in the logout.html file we copied, we use the self-created blocks card-header and card-body, as follows:

www.pythoneatstail.com

 

 

1. base.py

 

 

pip3 install django-allauth
AUTHENTICATION_BACKENDS = (
    ...
    # Needed to login by username in Django admin, regardless of `allauth`
    'django.contrib.auth.backends.ModelBackend',

    # `allauth` specific authentication methods, such as login by e-mail
    'allauth.account.auth_backends.AuthenticationBackend',
    ...
)

 

INSTALLED_APPS

'django.contrib.auth',
'django.contrib.messages',
'django.contrib.sites',

'allauth',
'allauth.account',
'allauth.socialaccount',
SITE_ID = 1

 

 

2. urls.py

 

pet/urls.py

from django.urls import path

urlpatterns = [
    ...
    path('accounts/', include('allauth.urls')),
    ...
]

 

 

3. HTML

 

{% extends 'account/base_card.html' %}

{% load i18n static %}

{% block title %}{% trans "Profile" %}{% endblock %}

{% block card-header %}
    <h3>{% trans "Account profile" %}</h3>
{% endblock %}

{% block card-body %}

    <div class="container">
       <div class="row">
            <div class="col border">
                <small>{% trans "First name" %}:</small><br>
                {{ request.user.first_name|default:'' }}
            </div>
            <div class="col border">
                <small>{% trans "Last name" %}:</small><br>
                {{ request.user.last_name|default:'' }}
            </div>
        </div>
    </div>

{% endblock %}

만약에 first_name 하고 last_name이 없을 경우 default를 줘서 공백으로 처리한다.

 

 

4. models.py

 

 

def get_absolute_url(self):
    return reverse('account_profile')

모델이 생성되었을 때, 바로 프로필 페이지로 넘어간다. account_profile은 profile page url의 name이다. 

https://www.pythoneatstail.com/en/overview-all-articles/add-extra-fields-custom-user-model/

 

A custom user model in Django with all common fields - PythonEats

The display name speaks for itself. We have added the possibility of translating the verbose name, by using gettext_lazy. When you are sure you will only use one language, you can of course omit this. In this tutorial we will consistently add the translati

www.pythoneatstail.com

 

1. admin.py

 

 

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import CustomUser

class CustomUserAdmin(UserAdmin):
    add_form = UserCreationForm
    form = UserChangeForm
    model = CustomUser
    list_display = ['pk', 'email', 'username', 'first_name', 'last_name']
    add_fieldsets = UserAdmin.add_fieldsets + (
        (None, {'fields': ('email', 'first_name', 'last_name', 'display_name', 'date_of_birth', 'address1', 'address2', 'zip_code', 'city', 'country', 'mobile_phone', 'additional_information', 'photo',)}),
    )
    fieldsets = UserAdmin.fieldsets + (
        (None, {'fields': ('display_name', 'date_of_birth', 'address1', 'address2', 'zip_code', 'city', 'country', 'mobile_phone', 'additional_information', 'photo',)}),
    )


admin.site.register(CustomUser, CustomUserAdmin)
  • fieldsets 
    • admin페이지에서 유저 수정할때 나타나는 입력폼 무엇으로 할건지
  • add_fieldsets
    • admin페이지에서 유저 추가할때 나타나는 입력폼 무엇으로 할건지\
  • list_display 
    • admin 리스트에서 보여지는 필드

 

 

2. models.py

 

 

from django.contrib.auth.models import AbstractUser
from django.core.validators import RegexValidator
from django.db import models
from django.utils.translation import gettext_lazy as _
from django_countries.fields import CountryField

class CustomUser(AbstractUser):
    display_name = models.CharField(verbose_name=_("Display name"), max_length=30, help_text=_("Will be shown e.g. when commenting"))
    date_of_birth = models.DateField(verbose_name=_("Date of birth"), blank=True, null=True)
    address1 = models.CharField(verbose_name=_("Address line 1"), max_length=1024, blank=True, null=True)
    address2 = models.CharField(verbose_name=_("Address line 2"), max_length=1024, blank=True, null=True)
    zip_code = models.CharField(verbose_name=_("Postal Code"), max_length=12, blank=True, null=True)
    city = models.CharField(verbose_name=_("City"), max_length=1024, blank=True, null=True)
    country = CountryField(blank=True, null=True)
    phone_regex = RegexValidator(regex=r"^\+(?:[0-9]●?){6,14}[0-9]$", message=_("Enter a valid international mobile phone number starting with +(country code)"))
    mobile_phone = models.CharField(validators=[phone_regex], verbose_name=_("Mobile phone"), max_length=17, blank=True, null=True)
    additional_information = models.CharField(verbose_name=_("Additional information"), max_length=4096, blank=True, null=True)
    photo = models.ImageField(verbose_name=_("Photo"), upload_to='photos/', default='photos/default-user-avatar.png')

    class Meta:
        ordering = ['last_name']

    def __str__(self):
        return f"{self.username}: {self.first_name} {self.last_name}"

 

Django 다국어 지원

from django.utils.translation import gettext_lazy as _
verbose_name=_('안녕하세요.')

 

Django 추가 필드 설치

pip install django-countries

 

 

3. forms.py

 

 

from .models import CustomUser
from wagtail.users.forms import UserCreationForm, UserEditForm


class WagtailUserCreationForm(UserCreationForm):
    class Meta(UserCreationForm.Meta):
        model = CustomUser
        widgets = {'date_of_birth': forms.DateInput(attrs={'type':'date'})}


class WagtailUserEditForm(UserEditForm):
    class Meta(UserEditForm.Meta):
        model = CustomUser
        widgets = {'date_of_birth': forms.DateInput(attrs={'type':'date'})}

 

 

4. base.py

 

 

os.path.join(BASE_DIR, 'userauth/templates/userauth/'),
AUTH_USER_MODEL = 'userauth.CustomUser'

WAGTAIL_USER_CREATION_FORM = 'userauth.forms.WagtailUserCreationForm'
WAGTAIL_USER_EDIT_FORM = 'userauth.forms.WagtailUserEditForm'
WAGTAIL_USER_CUSTOM_FIELDS = ['display_name', 'date_of_birth', 'address1', 'address2', 'zip_code', 'city', 'country', 'mobile_phone', 'additional_information', 'photo',]

 

 

5. html

 

 

{% extends "wagtailusers/users/create.html" %}

{% block extra_fields %}
    {% include "wagtailadmin/shared/field_as_li.html" with field=form.display_name %}
    {% include "wagtailadmin/shared/field_as_li.html" with field=form.date_of_birth %}
    {% include "wagtailadmin/shared/field_as_li.html" with field=form.address1 %}
    {% include "wagtailadmin/shared/field_as_li.html" with field=form.address2 %}
    {% include "wagtailadmin/shared/field_as_li.html" with field=form.zip_code %}
    {% include "wagtailadmin/shared/field_as_li.html" with field=form.city %}
    {% include "wagtailadmin/shared/field_as_li.html" with field=form.country %}
    {% include "wagtailadmin/shared/field_as_li.html" with field=form.mobile_phone %}
    {% include "wagtailadmin/shared/field_as_li.html" with field=form.additional_information %}
    {% include "wagtailadmin/shared/field_as_li.html" with field=form.photo %}
{% endblock extra_fields %}

 

1. postgres 설치

pip install psycopg2-binary

 

 

2. 데이터베이스 생성

set PGUSER=postgres
psql
psql -U postgres
CREATE USER usr_pet WITH PASSWORD '123';
CREATE DATABASE db_pet OWNER usr_pet;

 

 

3. base.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'db_pet',
        'USER': 'usr_pet',
        'PASSWORD': '123',
        'HOST': '127.0.0.1',
        'PORT': '5432',
    }
}

 

 

4. models.py

 

userauth/models.py

from django.contrib.auth.models import AbstractUser

class CustomUser(AbstractUser):
    pass

 

 

5. base.py

# custom user model

AUTH_USER_MODEL = 'userauth.CustomUser'

 

https://django-ninja.rest-framework.com/tutorial/routers/

 

Routers - Django Ninja

Routers Real world applications can almost never fit all logic into a single file. Django Ninja comes with an easy way to split your API into multiple modules using Routers. Let's say you have a Django project with a structure like this: ├── myprojec

django-ninja.rest-framework.com

 

Django Ninja에서 App마다 api.py와 schema.py를 생성해서 관리를 해야한다. 하지만 App이 많아질 수록 관리하기도 힘들어진다. 이럴경우 Router 기능을 사용하면 된다. 

 

 

1. Router 폴더 구조

 

각 App마다 api.py를 생성한다. (schema.py도 생성해준다.)

 

 

2. App별 api.py 작성

 

course/api.py

from typing import List

from ninja import Router

from .models import CoursePage
from . import schema


course_router = Router()

@course_router.get('/', response=List[schema.CourseSchema])
def courses(request):
    return CoursePage.objects.all()

@course_router.get('/{course_id}', response={200: schema.CourseSchema, 404: schema.NotFoundSchema})
def course(request, course_id: int):
    try:  
        course = CoursePage.objects.get(id=course_id)
        return course
    except CoursePage.DoesNotExist:
        return 404, {"message": "코스 페이지가 존재하지 않습니다."}

간단하게 CoursePage라는 모델의 정보를 가져오는 api를 구축하였다. 

Schema와 endpoint 구현은 기존의 NinjaAPI와 동일하게 작성하면 된다.

 

 

3. Project api.py 생성

 

myproject/api.py

import orjson

from ninja.renderers import BaseRenderer
from ninja import NinjaAPI

from course.api import course_router


# api 렌더링 (한글이 깨지는 문제) 
class ORJSONRenderer(BaseRenderer):
    media_type = "application/json"

    def render(self, request, data, *, response_status):
        return orjson.dumps(data)

api = NinjaAPI(renderer=ORJSONRenderer())

# 라우터 등록
api.add_router('/courses/', course_router)

api.add_router를 통해 url를 지정해주면 된다. 

'Back-End > Django-ninja' 카테고리의 다른 글

Django Ninja Method Not Allowed 오류  (0) 2021.12.09
Django Ninja Render  (0) 2021.11.30
Django Ninja Tutorial 5  (0) 2021.11.30
Django Ninja Tutorial 4  (0) 2021.11.30
Django Ninja Tutorial 3  (0) 2021.11.29
    def get_admin_display_title(self):
        return "Home Page is the Best"

 

'Back-End > Wagtail, Django' 카테고리의 다른 글

Wagtail, Django ModelAdmin Search  (0) 2022.01.14
Wagtail 프로젝트 배포  (0) 2021.12.20
Wagtail Routable  (0) 2021.12.03
Wagtail StreamField Options  (0) 2021.12.02
Wagtail Custom Page Properties  (0) 2021.12.02

BlogListingPage

    @route(r"november-2021/$", name="november_2021")
    @route(r"^year/(\d+)/(\d+)/$", name="blogs_by_year")
    def blog_by_year(self, request, year=None, month=None):
        context = self.get_context(request)
        
        return render(request, "blog/latest_posts.html", context)
    
    @route(r'^category/(?P<cat_slug>[-\w]*)/$', name="category_view")
    def category_view(self, request, cat_slug):
        context = self.get_context(request)
        
        try:
            category = BlogCategory.objects.get(slug=cat_slug)
        except Exception:
            category = None
            
        if category is None:
            pass
    
        context["posts"] = BlogDetailPage.objects.filter(categories__in=[category])
        return render(request, "blog/latest_posts.html", context)

 

blog_listing_page.html

    <a href="{% routablepageurl page 'latest_blog_posts' %}">View Latest Posts Only</a>

    <h2>Categories</h2>
    <ul>
        {% for cat in categories.all %}
        <li>
            <a href="{% routablepageurl page "category_view" cat.slug %}">{{ cat.name }}</a>
        </li>
        {% endfor %}
    </ul>

'Back-End > Wagtail, Django' 카테고리의 다른 글

Wagtail 프로젝트 배포  (0) 2021.12.20
Wagtail Changing the Admin Display Title  (0) 2021.12.03
Wagtail StreamField Options  (0) 2021.12.02
Wagtail Custom Page Properties  (0) 2021.12.02
Wagtail Custom Admin Tabs  (0) 2021.12.01

+ Recent posts