'SW/Django'에 해당되는 글 2건

  1. 2013.08.08 Django model field crash 해결책
  2. 2013.08.08 custom django-admin commands 사용하기
가끔가다 Django model 의 ManyToMany Relation 에서 Crash가 발생하는 경우가 있다. 예를 들면 다음과 같다.

 
class GameClaim(models.Model):
    target = models.ForeignKey(User)
    claimer = models.ForeignKey(User)
    isAccepted = models.BooleanField()

그러면 다음과 같은 오류를 내뱉게 된다.


Accessor for field 'target' clashes with related field 'User.gameclaim_set'. Add a related_name argument to the definition for 'target'.

Accessor for field 'claimer' clashes with related field 'User.gameclaim_set'. Add a related_name argument to the definition for 'claimer'.


일반적으로 FK를 만들면, Django는 gameclaim_set 이라는 reverse relation을 내부적으로 만들게 된다. 그런데, Gameclaim 안에 2개의 FK가 있기때문에 같은 gameclaim_set 이름의 충돌(Crash)이 나는 것이다. 해결책은 이 Reverse relation의 이름을 related_name을 이용하여 강제로 주는 것이다.


class GameClaim(models.Model):
    target = models.ForeignKey(User, related_name='gameclaim_targets')
    claimer = models.ForeignKey(User, related_name='gameclaim_users')
    isAccepted = models.BooleanField()

또한 ManyToManyField 도 다음과 같이 수정할 수 있다.
class User(models.Model):
    friendship = models.ManyToManyField("User", related_name = 'user_friendship')
    friendreq = models.ManyToManyField("User", related_name = 'user_friendreq')

'SW > Django' 카테고리의 다른 글

custom django-admin commands 사용하기  (0) 2013.08.08
Posted by 융잡
,

manage.py 를 사용하여 Django의 Application에 사용자 고유의 action을 등록할 수 있다. 여기서는 저번 tutorial 에서 만들었던 polls app을 위한 커스텀 명령어 closepoll 을 만들어볼 것이다. 이를 위해 management/commands 를 어플리케이션 디렉토리에 추가한다. 그러면 장고는 그 명령어들을 폴더 내의 각각의 모듈에 알아서 등록해준다.

즉 polls 앱은 아래와 같은 구조를 가질 것이다.

polls/
    __init__.py
    models.py
    management/
        __init__.py
        commands/
            __init__.py
            _private.py
            closepoll.py
    tests.py
    views.py

이렇게 하면, closepoll 명령어는 polls 어플리게이션을 포함하는 어떤 프로젝트에서도 사용가능하게 만들어질 것이다.

_private.py 모듈은 명령어 커맨드를 관리하는 역할으로서, 명령어 자체로는 사용할수 없다.
closepoll.py 모듈을 사용하기 위해 하나의 요구조건이 있는데, BaseCommand 또는 그의 sub클래스를 상속받는 Command 클래스를 재정의해야한다는 것이다.

커맨드를 구현하기 위해, polls/management/commands/closepoll.py 를 다음과 같이 편집한다.

from django.core.management.base import BaseCommand, CommandError
from polls.models import Poll

class Command(BaseCommand):
    args = ''
    help = 'Closes the specified poll for voting'

    def handle(self, *args, **options):
        for poll_id in args:
            try:
                poll = Poll.objects.get(pk=int(poll_id))
            except Poll.DoesNotExist:
                raise CommandError('Poll "%s" does not exist' % poll_id)

            poll.opened = False
            poll.save()

            self.stdout.write('Successfully closed poll "%s"' % poll_id)


  • 커맨드를 관리하면서 콘솔 결과창(디버그를 위해서든) 보기 위해, 당신은 

    stdout 와 stderr 대신에 self.stdout 와 self.stderr를 써야합니다.
    또한 ending 파라미터를 쓰지 않는 한, 개행문자가 자동으로 붙기 때문에 개행문자로 메시지를 끝낼 필요가 없습니다.

    self.stdout.write("Unterminated line", ending='')

이제 python manage.py closepoll <poll_id> 를 써서 새로운 custom command를 사용할 수 있다.

handle() 매서드는 poll_ids에 해당하는 각각의 poll.opened 들을 모두 False 로 바꿔준다.
만약 유저가 존재하지 않는 polls 에 접근한다면 CommandError 가 일어날 것이다. 다만poll.opened attribute 는 tutorial에는 존재하지 않고, polls.models.Poll이 이 예제를 위해 추가된 것이다.

주어진 poll을 닫는 것 대신 지우고 싶을 때는 굳이 추가적인 command 등록 없이 closepoll 을 변경하면 된다. 이런 커스텀 option은 반드시 option_list 에 다음처럼 추가되어야한다.

from optparse import make_option

class Command(BaseCommand):
    option_list = BaseCommand.option_list + (
        make_option('--delete',
            action='store_true',
            dest='delete',
            default=False,
            help='Delete poll instead of closing it'),
        )

    def handle(self, *args, **options):
        # ...
        if options['delete']:
            poll.delete()
        # ...

위 예제의 delete옵션은 또한 dictionary로도 접근가능하다. ex ) option['delete']
optparse 파이썬 문서로 가면 make_option 사용법에 대해 알 수 있을 것이다.

추가하자면, 모든 management commands 는 다음과 같은 default option을 받을 수도 있다.
--verbosity
--traceback.

아래는 번역 중

'SW > Django' 카테고리의 다른 글

Django model field crash 해결책  (0) 2013.08.08
Posted by 융잡
,