* Models에 method를 만드는 기준
- FE, BE 모두에 사용되고 여기저기서 갖다 쓸 때
class Review(core_models.TimeStampedModel):
""" Review Model Definition """
review = models.TextField()
accuracy = models.IntegerField()
communication = models.IntegerField()
cleanliness = models.IntegerField()
location = models.IntegerField()
check_in = models.IntegerField()
value = models.IntegerField()
user = models.ForeignKey(
"users.User", related_name="reviews", on_delete=models.CASCADE)
room = models.ForeignKey(
"rooms.Room", related_name="reviews", on_delete=models.CASCADE)
def __str__(self):
return f'{self.review} - {self.room}'
def rating_average(self):
avg = (self.accuracy +
self.communication +
self.cleanliness +
self.location +
self.check_in +
self.value)/6
return round(avg, 2)
이렇게 list_display에서 사용할 수 있음. __str__도 함수니까 이렇게 불러올 수 있다!
class ReviewAdmin(admin.ModelAdmin):
""" ReviewAdmin Admin Definition """
list_display = (
"__str__",
"rating_average",
)
all()로 가져온 QuerySet도 list의 일종이라서 iterable임. for in 문을 사용해서 데이터 접근 가능.
def total_rating(self):
all_reviews = self.reviews.all()
for review in all_reviews:
print(review.rating_average())
return 0
3.17
django에도 timezone을 관리하는 패키지가 있당
docs.djangoproject.com/en/3.1/topics/i18n/timezones/
from django.utils import timezone
class Reservation(core_models.TimeStampedModel):
def in_progress(self):
now = timezone.now().date()
return now > self.check_in and now < self.check_out
in_progress.boolean = True
in_progress.short_description = "Guest In Room"
def is_finished(self):
now = timezone.now().date()
return now > self.check_out
is_finished.boolean = True
is_finished.short_description = "Checked Out"
함수를 list_display에 보여줄 수 있지만 list_filter에는 적용이 안되는 것 같다..ㅠ
class ReservationAdmin(admin.ModelAdmin):
""" Reservation Admin Definition """
list_display = (
"room", "status", "check_in", "check_out", 'guest', "in_progress", "is_finished"
)
list_filter = ("status", )
- 이미지 업로드 관련해서 수정해보자
settings.py에서 이미지 관련 폴더의 root를 정해주고
docs.djangoproject.com/en/3.1/ref/settings/#media-root
# https://docs.djangoproject.com/en/3.1/ref/settings/#media-root
# https://docs.python.org/3/library/os.path.html#os.path.join
MEDIA_ROOT = os.path.join(BASE_DIR, "uploads")
models class에 정의된 ImageField에서 이미지를 upload 할 폴더 이름을 정해주면 된다.
-> uploads/avatars 안에 이미지가 저장됨
avatar = models.ImageField(upload_to="avatars", blank=True)
이미지의 URL을 지정해주면 URL로 이미지를 불러올 수 있다
docs.djangoproject.com/en/3.1/ref/settings/#media-url
MEDIA_URL이 non-empty면 반드시 "/"로 끝나야 함!
MEDIA_URL이 상대경로면 접두사로 서버에서 제공해주는 SCRIPT_NAME을 붙여야 함
(또는 / 를 붙여서 절대경로로 만든다)
MEDIA_URL = "/media/"
* config/settings.py 에서 개발 모드/릴리즈 모드를 변경할 수 있음
docs.djangoproject.com/en/3.1/topics/settings/#using-settings-in-python-code
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
개발 모드일 때 폴더 안의 파일들이 URL로 보이도록 할 것임
-> MEDIA_URL(media)와 MEDIA_ROOT(uploads)를 연결했다!
from django.conf import settings
from django.conf.urls.static import static
# 기존에 정의한 urlpatterns. 변수 이름 바꾸면 안됨!
urlpatterns = [
path('admin/', admin.site.urls),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
static 함수는 대강 이렇게 생겼다
URLPattern 으로 아래처럼 만든듯
def static(prefix, view=serve, kwargs):
return [
re_path(r'^%s(?P<path>.*)$' % re.escape(prefix.lstrip('/')), view, kwargs=kwargs),
]
def _path(route, view, kwargs=None, name=None, Pattern=None):
if isinstance(view, (list, tuple)):
# For include(...) processing.
pattern = Pattern(route, is_endpoint=False)
urlconf_module, app_name, namespace = view
return URLResolver(
pattern,
urlconf_module,
kwargs,
app_name=app_name,
namespace=namespace,
)
elif callable(view):
pattern = Pattern(route, name=name, is_endpoint=True)
return URLPattern(pattern, view, kwargs, name)
else:
raise TypeError('view must be a callable or a list/tuple in the case of include().')
>>> static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
[<URLPattern '^media/(?P<path>.*)$'>]
isinstance : docs.python.org/ko/3/library/functions.html#isinstance
view가 list나 tuple형이면 True, 아니면 False
callable : docs.python.org/ko/3/library/functions.html#callable
- image를 photo admin에서 보여주고 싶을 때
obj.file을 print해보면 string이 아니라 object임.
obj.file의 메소드 중 url을 사용해서 이미지의 url을 알 수 있다
<class 'django.db.models.fields.files.ImageFieldFile'>
img 태그를 리턴해서 웹에 보여질 수 있게 할 수 있다!
그치만 django가 string을 code로 인식하지 못하게 막고 있기 때문에 mark_safe 를 사용해줌
from django.utils.html import mark_safe
@admin.register(models.Photo)
class PhotoAdmin(admin.ModelAdmin):
""" Photo Admin Definition """
list_display = ('__str__', 'get_thumbnail',)
def get_thumbnail(self, obj):
# print(dir(obj.file))
return mark_safe(f'<img src="{obj.file.url}" />')
get_thumbnail.short_description = "Thumbnail"
- room admin에서 host를 검색할 수 있게 바꾸기
raw_id_fields : foreignkey나 manytomanyfield를 검색할 수 있게 Input 위젯으로 바꿔줌
docs.djangoproject.com/en/3.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.raw_id_fields
-> 값이 너무 많아지면 찾기 어려울 때 사용
=> Host 이름 대신 id(primary key)로 나옴
class RoomAdmin(admin.ModelAdmin):
raw_id_fields = ("host",)
- room admin에서 photo를 추가할 수 있게 photo admin 붙이기
InlineModelAdmin 을 사용하자
docs.djangoproject.com/en/3.1/ref/contrib/admin/#inlinemodeladmin-objects
TabularInline을 상속받은 class를 하나 만들어서
보고 싶은 admin class에 inlines 변수에 추가
class PhotoInline(admin.TabularInline):
model = models.Photo
@admin.register(models.Room)
class RoomAdmin(admin.ModelAdmin):
inlines = [PhotoInline, ]
TabularInline 대신 StackedInline을 사용해도 됨. 기능은 똑같음
TabularInline : Model을 옆으로 길게 보여줌
StackedInline : Model을 밑으로 길게 보여줌
class PhotoInline(admin.StackedInline):
model = models.Photo
@admin.register(models.Room)
class RoomAdmin(admin.ModelAdmin):
inlines = [PhotoInline, ]
- user admin에 room을 추가할 수 있게 room admin 붙이기
-> 위처럼 해주면 됨. 핵간단!
extra object이 기본값으로 3이길래 1로 줄여봄
from django.contrib import admin
from rooms import models as rooms_model
class RoomInline(admin.TabularInline):
model = rooms_model.Room
extra = 1
@admin.register(models.User)
class CustomUserAdmin(UserAdmin):
inlines = [RoomInline, ]
요것도 참고해보자
'개발 > AWS' 카테고리의 다른 글
Django 앱 만들기 - 모델 테스트 데이터를 자동으로 만들기 (0) | 2021.02.02 |
---|---|
Django 앱 만들기 - model의 save와 admin의 save_model을 오버라이딩 하기 (0) | 2021.02.02 |
Django 앱 만들기 - admin 패널 꾸미기, QuerySet, UserManager (0) | 2021.01.21 |
AWS 솔루션 (0) | 2021.01.20 |
Django 앱 만들기 - abstract class, ForeignKey, __str__, ManyToManyField (0) | 2021.01.19 |
댓글