[英]Is there a way to dynamically change the model used in an UpdateView with Django?
我正在編寫的應用程序包括用於創建事件的管道。 Event
由一類用戶提出,然后由管理員批准和編輯。 對我來說,問題在於有一個Event
子類ScoredEvent
,管理員應該可以即時指定它。 這將添加一個ScoredEvent.competition
外鍵,並覆蓋Event.participants
以使其通過一個表,該表包括每個參與者的相關分數。
理想情況下,普通用戶創建一個僅包含名稱和簡短說明的事件(通過限制非管理員CreateEventForm上的字段即可輕松完成),然后管理員可以在批准其他字段后返回並填寫其他字段事件。
我遇到的問題是,我不知道管理員在編輯時如何在批准表單視圖ScoredEvent
Event
更改為ScoredEvent
或如何實現。 我對頁面的看法是一個帶有標記為“與比賽聯系”復選框的編輯視圖,選中該復選框將允許管理員選擇一個比賽,然后將事件另存為ScoredEvent
。 如果未選中該框,則該事件將作為Event
繼續存在。
應該在哪里處理? 我的直覺是我應該在forms.py或模板中做一些特別的事情,但是我不知道應該從哪里開始。
class Event(models.Model):
"""Representation of any community event"""
name = models.CharField(max_length=50, unique_for_date="start_datetime")
slug = models.SlugField(max_length=57) # length +7 for datestamp
description = models.TextField()
location = models.CharField(max_length=100, blank=True)
start_datetime = models.DateTimeField('Start', blank=True)
end_datetime = models.DateTimeField('End', blank=True)
participants = models.ManyToManyField(Participant)
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.name)+'-'+datetime.now().strftime("%d%m%y")
super(Event, self).save(*args, **kwargs)
def __unicode__(self):
if self.start_datetime:
return "%s (%s)" % (self.name, self.start_datetime.date())
else:
return self.name
class ScoredEvent(Event):
"""Representation of an event that is tied to a competition"""
competition = models.ForeignKey(Competition)
participants = models.ManyToManyField(Participant, through="ScoredParticipant")
def is_scored(self):
"""Returns true if any of the participants has a score, else returns false"""
for participant in self.participants.objects.all():
if participant.score != 0:
return False
return True
class ScoredPartcipant(models.Model):
"""Participant and associated score for an event"""
participant = models.ForeignKey(Participant)
event = models.ForeignKey(ScoredEvent)
score = models.IntegerField(default=0)
覆蓋get_queryset
並根據是否發布以下字段之一而有所不同:
def get_queryset(self):
if self.request.POST.has_key('competition'):
return ScoredEvent.objects.all()
else:
return super(MyView, self).get_queryset()
因此,為了更好地解釋,您可以使用您提到的“ Tie to Competition”選項,通過Javascript向表單添加字段。 然后,如果該字段在POST中發送,它將改為使用ScoredEvent
。
如果要基於當前對象自動切換,則需要重寫get_object
。 類似於以下內容:
def get_object(self, queryset=None):
obj = super(MyView, self).get_object(queryset=queryset)
try:
return ScoredEvent.objects.get(pk=obj.pk)
except ScoredEvent.DoesNotExist:
return obj
它基本上試圖再次查找該對象,就好像它是一個ScoredEvent
,如果找到一個對象,則返回該版本,而不是Event
。
你也可能需要類似的覆蓋get_form_class
,以確保其驗證的ScoredEvent
應該如果它是一個ScoredEvent
或正在成為ScoredEvent
:
from django.forms import models as model_forms
def get_form_class(self):
if isinstance(self.object, ScoredEvent):
return model_forms.modelform_factory(ScoredEvent, ScoredEventForm)
else:
return super(MyView, self).get_form_class()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.