0

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

理想情况下,普通用户创建一个仅包含名称和简短描述的事件(通过限制非管理员 CreateEventForm 上的字段很容易做到),然后管理员可以在批准时返回并填写其他字段事件。

我遇到的问题是我不知道管理员在编辑审批表单视图时如何将其更改Event为 aScoredEvent或如何实现。我对该页面的设想是一个编辑视图,其中带有一个标记为“Tie To Competition”的复选框,选中该复选框后,管理员将可以选择一个竞赛,然后将事件保存为ScoredEvent. 如果未选中该框,则该事件将继续作为Event.

这个应该在哪里处理?我的直觉是我应该在 forms.py 或 Templates 中做一些特别的事情,但我不知道我应该从哪里开始。

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)
4

1 回答 1

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()

因此,只是为了更好地解释一下:您将使用您提到的“与竞争挂钩”选项通过 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

它基本上尝试再次查找对象,就好像它是 aScoredEvent并在找到时返回该版本,而不是Event.

您可能还需要类似地覆盖get_form_class以确保它在它是 a或正在成为 a时验证为ScoredEvent应该:ScoredEventScoredEvent

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()
于 2012-08-09T18:48:05.147 回答