[英]Extending Django User model - form population errors
我正在使用Player類擴展Django(v1.9)的內置User模型,以添加一些額外的屬性。
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,)
從Django管理面板創建用戶時,我並非總是需要創建播放器,因此有時僅會創建User。 結果,播放器和用戶ID不完全匹配。 事實證明,這在填充鏈接到Player的模型的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,該表單無法驗證,並且創建城市失敗。
我沒有從request.user獲取播放器ID的問題,並且可以在獲取POST數據后在驗證之前修正播放器ID。 我還添加了一個后保存掛鈎,以便始終創建Player,因此ID始終匹配。 但是似乎表單應該首先以玩家ID填充,因為用戶數據可以訪問並且是一對一的關系。
我在這里想念什么?
您所缺少的是,當實例化一個ModelForm來創建與某個現有對象相關的新行時,Django無法知道相關對象的ID。 您需要以某種方式告訴它。
一種方法是,在顯示表單以響應GET時,請使用表單構造函數的initial
參數:
myform = MyModelFormClass(None, initial={ 'myfkfield': myrelatedobject.pk })
現在,表單類知道在呈現表單時以及在發布表單時要預填充的值,該字段將與表單一起發布。
另一種方法是完全省略表單中的關系字段,然后在保存之前通過使用表單保存方法的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中都包含了這些內容,因此它不是必需的。但這不是Django的工作方式。 您需要從數據庫中獲取現有的對象,並將其與request.POST
數據一起傳遞給ModelForm構造函數。 然后,當您調用myform.save()
,它將驗證表單,將其數據與現有對象合並,然后保存該對象。 使用commit=False
導致這三個步驟中的最后一個被推遲,因此您可以在實際保存更新后的實例之前對其進行任何調整或檢查。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.