有没有办法用Django动态更改UpdateView中使用的模型?

时间:2012-08-09 18:39:05

标签: python django django-models django-forms django-views

我正在编写的应用程序包含一个用于创建事件的管道。 Event由一类用户提出,然后由管理员批准和编辑。对我来说问题是有一个EventScoredEvent的子类,管理员应该可以在运行中指定。这会添加ScoredEvent.competition外键并覆盖Event.participants,以便将它们放入包含每个参与者的关联分数的表中。

理想情况下,普通用户创建一个仅包含名称和简短描述的事件(通过限制非管理员CreateEventForm上的字段可以轻松完成),然后管理员可以返回并填写其他字段正在批准这项活动。

我遇到的问题是我不知道管理员在编辑时如何将Event更改为审核表单视图中的ScoredEvent或如何实现这一目标。我对该页面的看法是一个编辑视图,其中有一个标记为“Tie To Competition”的复选框,选中后,将允许管理员选择一个比赛,然后将该事件保存为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)

1 个答案:

答案 0 :(得分: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()

{{1}}