0618
오늘 할 일
- celery 이용해서 크롤링 실행 시간 줄이기
- book_id를 받을때 book 객체를 생성하고
- BookLocation.register_id Unique 속성 취소
- django model 수업 듣기
# 재귀적으로 외래키 사용
# on_delete의 옵션 = cascade, set, null, default, protected 5가지가 있음
class User(models.Model):
name = models.CharField(max_length=50)
instructor = models.ForeignKey('self', on_delete=models.SET_NULL, blank=True, null=True)
# user_set 의 경우 relatied_manager 가 역참조 할 수 있도록 동작
# Manufacturer가 아래 선언되서 인식하지 못하는 경우
# 문자열로 처리하여 인식할 수 있도록 함
class Car(models.Model):
manufacturer = models.ForeignKey(
'Manufacturer',
related_name='cars',
on_delete=models.CASCADE,
)
name = models.CharField(max_length=50)
def __str__(self):
return self.name
class Manufacturer(models.Model):
name = models.CharField(max_length=50)
def __str__(self):
return self.name
0619
오늘 할 일
-
celery 로 book 상세 페이지만 크롤링하는 코드 작성- 문제: update_or_create() 를 사용했는데 기존 book인스턴스를 업데이트하는게 아니라 새로운 book인스턴스를 생성하는게 문제
- 해결: default 설정이 필요함
오늘 공부한 내용
- 테이블 단위에서 작동할 때는 manager로 설정한다.
- 파이썬의 경우 오버로딩은 없다.
- Be careful with related_name and related_query_name 관련 예제
class RelatedUser(models.Model): name = models.CharField(max_length=50) def __str__(self): return self.name class PostBase(models.Model): author = models.ForeignKey( RelatedUser, on_delete=models.CASCADE, # 수정전 # related_name='posts', # 수정후 related_name='%(class)ss', ) created_at = models.DateTimeField(auto_now_add=True) class Meta: abstract = True class PhotoPost(PostBase): photo_url = models.CharField(max_length=500) class TextPost(PostBase): text = models.CharField(max_length=500) # 오류내용 abstract_base_classes.PhotoPost.author: (fields.E304) Reverse accessor for 'PhotoPost.author' clashes with reverse accessor for 'TextPost.author'. HINT: Add or change a related_name argument to the definition for 'PhotoPost.author' or 'TextPost.author'. abstract_base_classes.PhotoPost.author: (fields.E305) Reverse query name for 'PhotoPost.author' clashes with reverse query name for 'TextPost.author'.
abstract = True
의 경우 DB 에 테이블이 생기지 않음 그걸 상속받아서 사용한 자식테이블만 DB에 생성- Reverse accessor = related_name
- reverse query = related_query_name
- 상속을 통해 발생되는 문제를 해결하기 위해
related_name='%(class)ss',
이런식으로 지정
- Multi-table inheritance
# 부모와 자식 모두가 DB에 생성된다.
# 자식 테이블의 경우 place_ptr(pointer)_id 필드가 되어있음 이는 Place 부모 테이블의 id 값을 가지고 있음
# parent_link=True 를 통헤 위 필드를 재정의 할 수 있다.
class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)
def __str__(self):
return f'Place({self.name})'
class Restaurant(Place):
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)
def __str__(self):
return f'{self.pk} Restaurant'
class Supplier(Place):
# place_ptr = models.OneToOneField(Place)
customers = models.ForeignKey(
Place,
on_delete=models.CASCADE,
related_name='supplier_by_customer'
)
# 특정 Place의 p1이 있을 때
# Supplier.objects.filter(customer=p1)
# Supplier.objects.filter(place_ptr = p1)
# p1이 역방향일때 Manger 를 사용할 때
# related_name 안겹침
# p1.supplier_set <- MTM
# p1.supplier <- OTO (역방향 manager가 없음)
# pl이 역방향 Query 를 사용할 때
# 에러 코드
# multi_table.Supplier.customers: (fields.E305) Reverse query name for 'Supplier.customers' clashes with reverse query name for 'Supplier.place_ptr'.
# HINT: Add or change a related_name argument to the definition for 'Supplier.customers' or 'Supplier.place_ptr'.
# related_query_name,related_name 설정을 하지 았을 때의 기본값: 클래스명의 lowercase
# ---> supplier
# 겹치기 때문에 related_name을 설정해줘야 한다.
- relationships to models not yet defined 관련 오류
- 모델이 선언되기 전에 import를 해야하는 경우 모델 객체를 선언하기 보단 모델명을 선언 할 수 있다. 이때 다른 앱에서 import 하는 모델의 경우
appname.modelname
으로 작성하자.
- 모델이 선언되기 전에 import를 해야하는 경우 모델 객체를 선언하기 보단 모델명을 선언 할 수 있다. 이때 다른 앱에서 import 하는 모델의 경우
class Post(models.Model):
user = models.ForeignKey(
# 수정 전
# 'BlogUser',
# 수정 후 코드
'members.BlogUser',
on_delete=models.CASCADE,
related_name='my_posts',
)
title = models.CharField(max_length=100)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
@property
def like_users(self):
return f'{self.post_likes.all()}'
def __str__(self):
return self.title
class PostLike(models.Model):
post = models.ForeignKey(
'Post',
on_delete=models.CASCADE,
related_name='post_likes',
)
user = models.ForeignKey(
'members.BlogUser',
on_delete=models.CASCADE,
related_name='my_post_likes',
)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f'{self.user}님이 ({self.post})를 좋아합니다.'
# 오류
blog.Comment.user: (fields.E300) Field defines a relation with model 'BlogUser', which is either not installed, or is abstract.
blog.Comment.user: (fields.E307) The field blog.Comment.user was declared with a lazy reference to 'blog.bloguser', but app 'blog' doesn't provide model 'bloguser'.
toy_project 트러플 슈팅
- docker linux imgae install reids 하고 django celery 실행
- 우선 local 환경에서 docker에 redis설치하고, celery django 실행하는거 연습할 것
0620
오늘 할 일
-
Modeling 과제 함께 하기 - local redis로 코드 구현후, DokcerLocal 에서 진행해보기
toy_project 공부
- local환경에서 Docker에 redis 설치하고 celery를 실행시키려고 했는데, local DB 를 psql을 사용해서 Docker build자체가 안됬다. 결국 Dokcer-compose 관련 문서를 읽고 따라하는 중
- Dokcer-compose 참고 자료 « 읽고 정리해야한다.
- http://techstream.org/Web-Development/Development-Environment-for-Django-in-docker-compose
- Docker psql connect 참고
- Django celery reids
Django 공부
# blog/admin.py
from django.contrib import admin
# Register your models here.
from .models.comment import CommentLikeAdmin, CommentAdmin
from .models.post import PostAdmin, PostLikeAdmin
from .models import Post, PostLike, Comment, CommentLike
admin.site.register(Post, PostAdmin)
admin.site.register(PostLike, PostLikeAdmin)
admin.site.register(Comment, CommentAdmin)
admin.site.register(CommentLike, CommentLikeAdmin)
# post.py
from django.contrib import admin
from django.db import models
class CommonInfo(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
abstract = True
class Post(CommonInfo):
user = models.ForeignKey(
'members.BlogUser',
on_delete=models.CASCADE,
related_name='my_posts',
)
title = models.CharField(max_length=100)
content = models.TextField()
@property
def like_users(self):
return f'{self.post_likes.all()}'
def __str__(self):
return self.title
# 상속 받은 필드의 경우 Admin 페이지에서 볼 수 없어서
# 해당 필들르 보기 위해 아래와 같이 설정
class PostAdmin(admin.ModelAdmin):
readonly_fields = ('created_at',)
- abstract로 모델을 상속 받는 경우, amdin 페이지에서 상위 클래스의 필드를 볼 수 없다. 그 경우
PostAdmin
처럼 클래스를 하나 만들고, 원하는 필드를 readonly_fields로 설정하자
0621
pipenv 설치
- 참고자료
/* .zshrc */ # add "$HOME/.local/bin" to PATH variable export PATH=$HOME/.local/bin:$PATH
수업
- pipenv
Virtualenv location: /home/kahee/.local/share/virtualenvs/instagram-sb0x6JIC
>> pipenv --python 3.6.5 >> pipenv install django /* 이걸 입력해야 가상환경이 적용됨 */ To activate this project's virtualenv, run the following: $ pipenv shell >> pipenv shell
Docker-compose
- 생각보다 runserver하고 이해하는 부분이 어렵다 ㅜㅜ 도커에서 런서버까지 실행되는 이미지 만들고 거기서 reids 설치하고나서 로컬에서 celery 실행하는 것 연습할것
0622
오늘 할 일
- 인스타그램 수업 따라하기
- docker-compose, local reids 사용해보기
mac pipenv 경로
- /Users/(내계정)/.local/share/virtualenvs/~~~
toy_project 이야기
- 드디어 docker compose 를 활용해서 psql 과 django runserver를 실행시켰다. 이거 왜 이렇게 되는지는 정리해아함.
- dockerfile에서 redies 설치 후, Command를 이용해서 celery 명령어를 실행시켜보자
- AWS에선 ElastiCache 생성하고 도커에 이미 설치된 redis를 무시한고 django -celery 주소만 제대로 바꿔서 실행시켜볼 것
/* redis 설치 및 실행 */
wget http://download.redis.io/redis-stable.tar.gz
tar xvzf redis-stable.tar.gz
cd redis-stable
sudo apt-get install make
sudo apt-get install gcc
sudo apt-get install tcl
sudo apt-get install build-essential
sudo apt-get update
## if there is another error like "fatal error: jemalloc/jemalloc.h: No such file or directory"
## just run "make distclean"
make
make test
[redis] https://hackernoon.com/docker-tutorial-getting-started-with-python-redis-and-nginx-81a9d740d091 [redis 설치 with dockerfile] https://github.com/dockerfile/redis