2017-05-15 5 views
0

일부 추가 속성을 추가하기 위해 장고 (v1.9) 내장 사용자 모델을 Player 클래스로 확장했습니다.Django 확장 사용자 모델 - 양식 채우기 오류

class Player(models.Model): 
    TIMEZONES=() 
    user = models.OneToOneField(User, on_delete=models.CASCADE) 
    ... (player-specific properties here) 
    time_zone = models.CharField(max_length=255, choices=PRETTY_TIMEZONE_CHOICES, blank=True, null=True,) 

장고 관리자 패널에서 사용자를 만들 때 항상 플레이어를 만들 필요는 없으므로 사용자 만 생성됩니다. 따라서 플레이어 ID와 사용자 ID가 정확히 일치하지 않습니다. 이와 같은, 플레이어에 연결되어 모델의 ModelForms을 채울 때이 문제로 연결 밝혀 : 새로운 도시를 만들 때

class City(models.Model): 
    player = models.ForeignKey(Player, on_delete=models.CASCADE) 
    name = models.CharField(max_length = 100) 
    x_coord = models.SmallIntegerField() 
    y_coord = models.SmallIntegerField() 
    region = models.CharField(max_length = 100) 
    def __unicode__(self): 
     return str(self.player) + "-" + str(self.name) 
    class Meta: 
     db_table = 'cities' 

class CityForm(ModelForm): 
    class Meta: 
     model = City 
     fields = (
      'name', 
      'player', 
      'x_coord', 
      'y_coord', 
      'region') 

이 modelForm 사용됩니다. 사용자 ID와 플레이어 ID가 일치하면 문제가 없으며 플레이어 ID가 양식에 채워지고 도시가 성공적으로 만들어집니다. 사용자 ID와 플레이어 ID가 다른 경우 플레이어 ID가 양식에 채워지지 않고 양식의 유효성을 검사하지 못하고 도시 만들기가 실패합니다.

Player ID를 request.user에서 가져 오는 데 아무런 문제가 없으며 POST 데이터를 가져온 후 유효성을 검사하기 전에 플레이어 ID를 수정할 수 있습니다. 또한 Player가 항상 만들어 지도록 사후 저장 후크를 추가 했으므로 ID는 항상 일치합니다. 하지만 사용자 데이터에 액세스 할 수 있고 일대일 관계이기 때문에 양식 에 먼저 플레이어 ID가 채워져 있어야합니다.

무엇이 여기에 있습니까?

답변

0

누락 된 점은 ModelForm을 인스턴스화하여 기존 개체와 관련된 새 행을 만들 때 장고는 관련 개체의 ID를 알 수 없다는 것입니다. 어떻게 든 말해야합니다.

myform = MyModelFormClass(None, initial={ 'myfkfield': myrelatedobject.pk }) 

는 이제 폼 클래스 가치가 무엇인지 사전 채우기를 알고 : 그 작업을 수행하는

한 가지 방법은 당신이 GET에 대한 응답으로 양식을 표시 할 때, 폼 생성자에 initial 인수를 사용한다 양식이 렌더링 될 때, 양식이 게시 될 때 해당 필드가 함께 게시됩니다.

당신이 방법 저장 폼에 commit 인수를 사용하여, 저장하기 전에 그 다음, 모두 양식에서 관계 필드를 생략 나중에 기입하는 것입니다 할 수있는 다른 방법 :

myform = MyModelFormClass(request.POST) 
# this causes form values to be filled into the instance without actually 
# writing to the database yet. 
myinstance = myform.save(commit=False) 
myinstance.myfkfield = myrelatedobject 
# now really write to database 
myinstance.save() 

주 이것이 삽입을위한 것이라고 업데이트를 들어, 다음과 같이 당신의 modelform 생성자에 기존 개체를 제공해야합니다 : 인스턴스없이

myinstance = MyModel.objects.get(pk=self.kwargs.pk) 
myform = MyModelFormClass(request.POST, instance=myinstance) 

이 ModelForm가 데이터베이스에 업데이트 무엇을 행 모른다. 이 모든 것이 HTML에 존재하므로 필요하지 않아야한다고 생각 하겠지만 장고가 작동하는 방식은 아닙니다. 데이터베이스에서 기존 개체를 가져와 request.POST 데이터와 함께 ModelForm 생성자에 전달해야합니다. 그런 다음 myform.save()을 호출하면 양식의 유효성을 검사하고 데이터를 기존 개체와 병합 한 다음 개체를 저장합니다. commit=False을 사용하면 마지막 세 단계가 지연되므로 실제로 저장되기 전에 업데이트 된 인스턴스를 조정하거나 검사 할 수 있습니다.

+0

ID에 대한 어떤 가정도하지 않았습니다. 반대의 경우, 플레이어 ID가 modelForm에 올바르게 채워질 것이라고 당연시했습니다. 이 문제는 여러 개의 도시 ID가있는 것은 아닙니다. 사용자의 플레이어 ID가 도시 작성 양식에 채워지지 않는 새로운 도시를 만드는 경우입니다. – seadeer

+0

아,이 문제를 해결하기 위해 노력하고 있었다는 것을 알았습니다. 대답을 업데이트 할 것입니다. –

+0

그래, 제 대답이 바뀌 었으니 잘하면 도움이됩니다. 당신이 아직도 이해가 안되면 나는 그것을 정리하려고 노력할 수 있습니다. –