- ViewData
- 하드 윈도우 복사
- 바코드 생성하기
- SSD 복사
- 파일업로드 유효성체크
- XSS PHP
- 말줄임표시
- jquery 바코드생성
- javascript 바코드스캔
- TempData
- php 캐쉬제거
- javascript 바코드 생성
- ASP.Net Core 404
- 하드 마이그레이션
- jquery 바코드
- javascript 유효성체크
- django 엑셀불러오기
- Mac Oracle
- 맥 오라클설치
- 404에러페이지
- asp.net core Select
- asp.net Select
- asp.net dropdownlist
- XSS방어
- 강제이동
- 파일업로드 체크
- 바코드 스캔하기
- ViewBag
- 타임피커
- javascript redirection
웹개발자의 기지개
[Django] ModelAdmin 상에서 list_display 내에서 ManyToMany 필드의 상위 세부 내역조회 하기 - (다대다관계 2) 본문
[Django] ModelAdmin 상에서 list_display 내에서 ManyToMany 필드의 상위 세부 내역조회 하기 - (다대다관계 2)
http://portfolio.wonpaper.net 2022. 5. 24. 23:29다:다 관계로 이루어진 다음과 같은 모델 자료가 있다고 할때
ManyToMany 필드를 통하여 상위 세부 내역을 조회하고 이를 관리자페이지상의 ModelAdmin 형태로 나타내고자 한다.
다음 캡처이미지와 소스는 필자가 나름 고찰하여 만들어 보았다.
Member 와 Lecture 가 다:다 관계의 모델이고, Lecture Member 가 1:다:1의 중간 테이블모델이다.
SQL 구문과 같이 다대다 관계는 원래 1:다:1 형태의 테이블로 구분하여 처리해 준다.
장고상의 ORM 역시 이부분과 동일하게 생각하면 된다.
그리고, Member 모델의 데이터는 아래와 같다.
[ member/models.py ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
from django.db import models
class Member(models.Model):
mem_id = models.CharField(db_column='mem_id',max_length=50, unique=True)
passwd = models.CharField(db_column='passwd', max_length=255)
name = models.CharField(db_column='name', max_length=50)
email = models.CharField(db_column='email', max_length=50, blank=True)
usage_flag = models.CharField(db_column='usage_flag', max_length=10, default='y')
log_cnt = models.IntegerField(db_column='log_cnt', default=0)
reg_date = models.DateTimeField(db_column='reg_date', auto_now_add=True)
update_date = models.DateTimeField(db_column='update_date', auto_now=True)
class Meta:
# managed = False
db_table = 'member'
def __str__(self):
return '이름 : ' + self.name + ", 이메일 : " + self.email
|
cs |
[ lecture/models.py ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
from django.db import models
from member.models import Member
class Lecture(models.Model):
member = models.ManyToManyField(Member, through='LectureMember', blank=True)
lecture_name = models.CharField(db_column='lecture_name', max_length=255)
content = models.TextField(db_column='content', blank=True)
read_num = models.IntegerField(db_column='read_num', default=0)
reg_date = models.DateTimeField(db_column='reg_date', auto_now_add=True)
update_date = models.DateTimeField(db_column='update_date', auto_now=True)
image1 = models.ImageField(db_column='image1', upload_to='lecture/image1/%Y/%m/%d/', max_length=255, blank=True)
upfile1 = models.FileField(db_column='upfile1', upload_to='lecture/upfile1/%Y/%m/%d/', max_length=255, blank=True)
class Meta:
db_table = 'lecture'
def __str__(self):
return f"강의명 : {self.lecture_name}"
# 1:다:1 테이블
class LectureMember(models.Model):
member = models.ForeignKey(Member, db_column='member_id', on_delete=models.CASCADE, related_name='memberOf')
lecture = models.ForeignKey(Lecture, db_column='lecture_id', on_delete=models.CASCADE, related_name='lectureOf')
jumsu = models.IntegerField(db_column='jumsu', default=0)
reg_date = models.DateTimeField(db_column='reg_date', auto_now_add=True)
class Meta:
db_table = 'lecture_member'
def __str__(self):
return f"강의 : {self.lecture.lecture_name}, 회원 : {self.member.name}"
|
cs |
위의 소스중에 7라인 ManyToMany 가 이부분이다.
through='LectureMember' 을 통하여 1:다:1 에서 다에 해당하는 LectureMember 모델을 따로 두고 있는데,
실제상에서는 이 옵션을 만들지 않아도 장고는 내부적으로 처리되는데,
필자는 전체 프로그램 흐름 이해를 위해서 만들어 두었다.
[ /member/admin.py ]
1
2
3
4
5
6
7
8
|
from django.contrib import admin
from .models import Member
class MemberAdmin(admin.ModelAdmin):
list_display = ('mem_id', 'name', 'email')
admin.site.register(Member, MemberAdmin)
|
cs |
[ /lecture/admin.py ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
from django.contrib import admin
from .models import Lecture, LectureMember
class LectureAdmin(admin.ModelAdmin):
list_display = ('lecture_name', 'get_members_mem_id', 'get_members_name', 'update_date')
def get_members_mem_id(self, obj):
return ', '.join([m.mem_id for m in obj.member.all()])
get_members_mem_id.short_description = '아이디'
def get_members_name(self, obj):
return ', '.join([m.name for m in obj.member.all()])
get_members_name.short_description = '이름'
admin.site.register(Lecture, LectureAdmin)
class LectureMemberAdmin(admin.ModelAdmin):
list_display = ('get_lecture_name', 'get_mem_id', 'get_member_name', 'jumsu', 'reg_date' )
def get_lecture_name(self, obj):
return obj.lecture.lecture_name
get_lecture_name.short_description = '강의명'
def get_mem_id(self, obj):
return obj.member.mem_id
get_mem_id.short_description = '아이디'
def get_member_name(self, obj):
return obj.member.name
get_member_name.short_description = '이름'
admin.site.register(LectureMember, LectureMemberAdmin)
|
cs |
마지막 /lecture/admin.py 소스는 관리자페이지 소스이다.
8~ 10라인과 같이 get_members_mem_id, get_members_name 함수를 각각 만들고,
ManyToMany 필드와 연결된 member 모델을 [m.mem_id for m in obj.member.all()] 이런식으로 리스트 형태로 모아서 조회할 수 있다.
참고 : https://stackoverflow.com/questions/18108521/many-to-many-in-list-display-django
'python > Django' 카테고리의 다른 글
[Django] Template filter 알아보기 (0) | 2023.05.19 |
---|---|
[Django] 엑셀 읽고 딕셔너리(Dictionary) 형태로 Django 페이지에 불러오기 (0) | 2022.09.02 |
[Django] ModelAdmin 상에서 list_display 내에서 ForeignKey 필드를 불러오는 방법 (일대다 관계 2) (0) | 2022.05.20 |
[Django] ORM - N:N 관계 (ManytoManyField) (다대다관계 1) (0) | 2022.05.14 |
[Django] ORM - 1:N 관계 (ForeignKey) (일대다관계 1) (0) | 2022.05.14 |