1. Django Tutorial(Airbnb) - MEDIA_ROOT & MEDIA_URL

ID์งฑ์žฌยท2021๋…„ 7์›” 29์ผ
0

Django

๋ชฉ๋ก ๋ณด๊ธฐ
11/43
post-thumbnail

๐ŸŒˆ MEDIA_ROOT & MEDIA_URL

๐Ÿ”ฅ MEDIA_ROOT

๐Ÿ”ฅ MEDIA_URL

๐Ÿ”ฅ Admin Panel์— ์ด๋ฏธ์ง€ ํŒŒ์ผ ๋‚˜ํƒ€๋‚ด๊ธฐ


1. MEDIA_ROOT

  • BASE_DIR ๊ธฐ์ค€์œผ๋กœ ๋ชจ๋“  file๋“ค์ด ์ €์žฅ๋  ์œ„์น˜๋Š” settgins.py์— MEDIA_ROOT๋ฅผ ํ†ตํ•ด ์„ค์ •ํ•  ์ˆ˜ ์žˆ์–ด์š”!

1) settgins.py & .gitignore

  • MEDIA_ROOT๋Š” ImageField๋กœ ์—…๋กœ๋“œ๋˜๋Š” ์ด๋ฏธ์ง€ ํŒŒ์ผ์ด ์ €์žฅ๋  ๊ฒฝ๋กœ๋ฅผ ์ง€์ •ํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•ด์š”.
  • BASE_DIR์€ Project ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์˜๋ฏธํ•ด์š”,, ์ด์— Project ๋””๋ ‰ํ† ๋ฆฌ ๋‚ด์— "uploads"์— ์ด๋ฏธ์ง€ํŒŒ์ผ์„ ์ €์žฅํ•˜๋ ค๋ฉด ์•„๋ž˜์ฒ˜๋Ÿผ ์„ค์ •ํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.
    • ๐Ÿ”Ž MEDIA_ROOT = os.path.join(BASE_DIR, "uploads")
  • "uploads" ๋””๋ ‰ํ† ๋ฆฌ ๋‚ด์˜ ์ด๋ฏธ์ง€ ํŒŒ์ผ์„ .gitignore์— ์˜ฌ๋ฆฌ์ง€ ์•Š๊ธฐ ์œ„ํ•ด์„œ๋Š” .gitignore์— ํ•ด๋‹น ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•ด์ค๋‹ˆ๋‹ค.
๐Ÿ”Ž settgins.py
# MEDIA ROOT
MEDIA_ROOT = os.path.join(BASE_DIR, "uploads") # ๐Ÿ‘ˆ MEDIA_ROOT ์ง€์ •
๐Ÿ”Ž .gitignore
# MEDIA
uploads/

2) upload_to

  • ์ด๋ฏธ์ง€ ํŒŒ์ผ๋“ค์ด ์ €์žฅ๋  "uploads" ๋””๋ ‰ํ† ๋ฆฌ์— ๋‚ด์— ๋ชจ๋“  ์‚ฌ์ง„์ด ์ €์žฅ๋˜๋ฉด ์–ด๋Š ๋ชจ๋ธ์—์„œ ์ €์žฅ๋œ ์ด๋ฏธ์ง€ ํŒŒ์ผ์ธ์ง€ ํŒŒ์•…ํ•˜๋Š”๋ฐ ์–ด๋ ค์›€์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
  • ์ด์— ํ•ด๋‹น ๋ชจ๋ธ์˜ ํ•„๋“œ์— ๋”ฐ๋ผ ์—…๋กœ๋“œ ๋˜๋Š” ์ด๋ฏธ์ง€ ํŒŒ์ผ์„ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์œ„ํ•ด "upload_to" ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”!
<class Photo(core_models.TimeStampedModel):
    """Photo Model Definition"""
    caption = models.CharField(max_length=80)
    file = models.ImageField(upload_to="room_photos",)
    room = models.ForeignKey("Room", related_name="photos", on_delete=models.CASCADE)
    def __str__(self):
        return self.caption

2. MEDIA_URL

1) settgins.py

  • ์›น๋ธŒ๋ผ์šฐ์ €์—์„œ URL์„ ํ†ตํ•ด ์ €์žฅ๋œ ์ด๋ฏธ์ง€ ํŒŒ์ผ์— ์ ‘๊ทผํ•  ๋•Œ, ์–ด๋–ค ๊ฒฝ๋กœ์—์„œ ํ•ด๋‹น file์„ ํƒ์ƒ‰ํ• ์ง€ ์ง€์ •ํ•ด์ฃผ๋Š” ๊ฒƒ์ด MEDIA_URL ์ด์—์š”!
๐Ÿ”Ž settgins.py
# MEDIA ROOT
MEDIA_ROOT = os.path.join(BASE_DIR, "uploads") # ๐Ÿ‘ˆ MEDIA_ROOT ์ง€์ •
MEDIA_URL = "/media/" # ๐Ÿ‘ˆ MEDIA_URL ์ง€์ •

2) config.urls.py

  • MEDIA_ROOT์™€ MEDIA_URL์„ ์„ค์ •ํ•˜๊ณ  ๊ฒฝ๋กœ๋กœ ์ด๋ฏธ์ง€ ํŒŒ์ผ์„ ํƒ์ƒ‰ํ•  ๋•Œ์•„๋ž˜์™€ ๊ฐ™์€ ์˜ค๋ฅ˜ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์€ urls.py์˜ ๊ฒฝ๋กœ ์„ค์ •์ด ๋˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์ด์—์š”
  • ๊ฒฝ๋กœ๋ฅผ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด urls.py์—์„œ settgins.py์— ์ ‘๊ทผํ•ด์•ผํ•˜๋Š”๋ฐ์š”,, ํŒŒ์ผ์„ ์ž„ํฌํŠธํ•˜๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ, ํŒŒ์ผ์— ๋ฐ˜์˜ํ•œ ๋‚ด์šฉ์„ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด settgins.py๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด import ํ•ฉ๋‹ˆ๋‹ค.
    • ๐Ÿ”Ž from django.conf import settings
  • Django์—์„œ ์ •์  ํŒŒ์ผ์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด์„œ static์„ import ํ•ด์•ผ ํ•ด์š”!
    • ๐Ÿ”Ž from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path
from django.conf import settings # ๐Ÿ‘ˆ "settigns.py" import
from django.conf.urls.static import static # ๐Ÿ‘ˆ "static" import
urlpatterns = [
    path("admin/", admin.site.urls),
]
if settings.DEBUG: # ๐Ÿ‘ˆ ํ˜„์žฌ ๊ฐœ๋ฐœ๋ชจ๋“œ๋ผ๋ฉด(DEBUG=True)
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

3. Admin Panel์— ์ด๋ฏธ์ง€ ํŒŒ์ผ ๋‚˜ํƒ€๋‚ด๊ธฐ

1) Outline Admin Panel

  • ์ด๋ฏธ์ง€ ํŒŒ์ผ์„ Admin Panel์— ๋‚˜ํƒ€๋‚˜๊ธฐ ํ•˜๊ธฐ ์œ„ํ•ด ์ด๋ฏธ์ง€ ๊ฒฝ๋กœ๋ฅผ img ํƒœ๊ทธ์— ๋‹ด์•„ returnํ•ด ๋ณผ๊ป˜์š”:)
@admin.register(models.Photo)
class PhotoAdmin(admin.ModelAdmin):
    """Photo Admin Dfinition"""
    list_display = ("__str__", "get_thumbnail", )
    def get_thumbnail(self, obj):
    	# print(dir(obj.file))
    	# print(dir(obj.file.url))        
        return f"<img src="{obj.file.url}"/>"
    get_thumbnail.short_description = "Thumbnail"
  • ๋ฐ˜ํ™˜ํ•˜์˜€๋”๋‹ˆ,, ์ด๋ฏธ์ง€๊ฐ€ ์•„๋‹Œ string์œผ๋กœ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค
  • ์ด๋Š” XSS(Cross-Site Scripting)์™€ ๊ฐ™์€ ๊ณต๊ฒฉ์œผ๋กœ๋ถ€ํ„ฐ Django๊ฐ€ ์›น์‚ฌ์ดํŠธ๋ฅผ ๋ณดํ˜ธํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด์—์š”! ์ด์— Django์—๊ฒŒ ์ด "tag๋Š” ์•ˆ์ „ํ•œ html tag์•ผ"๋ผ๊ณ  ์•Œ๋ ค์ค˜์•ผํ•˜๋Š”๋ฐ์š”,, ์ด๋Ÿด ๋•Œ mark_safe()๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. mark_safe() ์•„๋ž˜ ์œ„์น˜ํ•˜๊ณ  ์žˆ์–ด์š”!
    • ๐Ÿ”Ž from django.utils.html import mark_safe
from django.utils.html import mark_safe
@admin.register(models.Photo)
class PhotoAdmin(admin.ModelAdmin):
    """Photo Admin Dfinition"""
    list_display = ("__str__", "get_thumbnail", )
    def get_thumbnail(self, obj):       
        return mark_safe(f'<img width="50px" src="{obj.file.url}"/>')
    get_thumbnail.short_description = "Thumbnail"

2) Inline Admin Panel

  • Admin ์•ˆ์— ๋‹ค๋ฅธ Admin์„ ๊ฐ€์ ธ์™€ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ InlineModelAdmin ๊ธฐ๋Šฅ์ด๋ผ ํ•˜๋Š”๋ฐ์š”,, InlineModelAdmin ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” Inline์— ํ‘œ์‹œํ•  ๋ชจ๋ธ์„ Class๋กœ ๋งŒ๋“  ๋’ค, ๋‚˜ํƒ€๋‚ด๊ณ ์žํ•˜๋Š” Admin Class ๋‚ด๋ถ€์— "inline" ์†์„ฑ์œผ๋กœ ํ‘œ์‹œํ•  ๋ชจ๋ธ์˜ ํด๋ž˜์Šค๋ฅผ ๋ช…์‹œํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.
  • ์ด๋ ‡๊ฒŒ ๋‚ด๋ถ€์— Admin Panel์„ ๊ฐ€์ ธ์™€ ์‚ฌ์šฉํ•˜๋ฉด, Admin Site๋ฅผ ์ด๋™ํ•˜๋ฉฐ ์ž‘์—…ํ•˜๋Š” ์ˆ˜๊ณ ๋ฅผ ์ค„์—ฌ์ค๋‹ˆ๋‹ค:)
from django.contrib import admin
from . import models
class PhotoInline(admin.TabularInline): # ๐Ÿ‘ˆ Inline์œผ๋กœ ํฌํ•จ๋  ๋ชจ๋ธ์„ Class๋กœ ์ƒ์„ฑ
    model = models.Photo
@admin.register(models.Room)
class RoomAdmin(admin.ModelAdmin):
    """Room Admin Dfinition"""
    inlines = (PhotoInline,) # ๐Ÿ‘ˆ inlines ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ InlineModelAdmin ๋ช…์‹œ

profile
Keep Going, Keep Coding!

0๊ฐœ์˜ ๋Œ“๊ธ€