簡體   English   中英

有沒有一種方法可以動態更改Django的UpdateView中使用的模型?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM