TIL - 0618-0622

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으로 작성하자.
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