2009-08-12 56 views
1

我們要做的是使用不同模型的某個查詢集填充帶有初始值的內聯表單列表。我們有產品,度量標準(某些類別或類型或評級)和評級,它將實際評級和關聯度量存儲到產品中。InlineFormSet與不同模型的查詢集

class Product(models.Model): 
    name = models.CharField(max_length=100) 
    price = models.IntegerField(max_length=6) 

class Metric(models.Model): 
    name = models.CharField(max_length=80) 
    description = models.TextField() 


class Rating(models.Model) 
    rating = models.IntegerField(max_length=3) 

    metric = models.ForeignKey(Metric) 
    product = models.ForeignKey(Product) 

我們要做的最終結果是產品管理頁面上產品的所有可能評級列表。如果我們的數據庫中有20個度量標準,當我們轉到產品頁面時,我們希望在頁面上看到20個評級表單,每個表單都與不同的度量標準綁定。我們無法使用基於評分的查詢集來填充頁面,因爲特定產品/度量標準組合的評分可能不存在。

我們一直在尋找所有的形式和在Django表單集代碼,並且都希望能拿出這麼簡單的解決方案:

http://www.thenestedfloat.com/articles/limiting-inline-admin-objects-in-django

他只是將覆蓋東西BaseInlineFormSet並給出它的內聯。也許我們可以製造像

class RatingInlineFormset(BaseInlineFormset): 

隨着一些覆蓋。有任何想法嗎?

回答

0

您是否在尋找管理員或前端解決方案?管理方式如下,你可以反向工程也得到了類似的前端解決方案:

# admin.py 

class RatingInline(admin.StackedInline): 
    model = Rating 

class ProductAdmin(admin.ModelAdmin): 
    inlines = [ 
     RatingInline 
    ] 

class MetricAdmin(admin.ModelAdmin): 
    pass 

class RatingAdmin(admin.ModelAdmin): 
    pass 

admin.site.register(Product, ProductAdmin) 
admin.site.register(Metric, MetricAdmin) 
admin.site.register(Rating, RatingAdmin) 
0

我已成功地實現類似的功能有點像這樣:

from django.forms.models import BaseInlineFormSet 
from django.forms.models import inlineformset_factory  

class RawQueryAdapter(object): 
    """ 
    Implement some extra methods to make a RawQuery 
    compatible with FormSet, which is expecting a QuerySet 
    """ 
    ordered = True 

    def __init__(self, qs): 
     self.qs = qs 
     self.db = qs.db 

    def filter(self, *args, **kwargs): 
     return self 

    def __len__(self): 
     return len(list(self.qs)) 

    def __getitem__(self, key): 
     return self.qs[key] 

class BaseRatingFormSet(BaseInlineFormSet): 
    def __init__(self, *args, **kwargs): 
     sql = """ 
      SELECT r.id, %s as product_id, m.id as metric_id 
      FROM myapp_metric m 
      LEFT JOIN myapp_rating r ON m.id = r.metric_id 
      AND r.product_id = %s 
     """ 
     id = kwargs['instance'].id or 'NULL' 
     qs = RawQueryAdapter(Rating.objects.raw(sql % (id, id))) 
     super(BaseRatingFormSet, self).__init__(queryset=qs, *args, **kwargs) 

    def _construct_form(self, i, **kwargs): 
     pk_key = "%s-%s" % (self.add_prefix(i), self.model._meta.pk.name) 
     if self.data.get(pk_key) == '': 
      # Skip parent (BaseModelFormSet) implementation as it won't work 
      # with our injected raw data 
      if i < self.initial_form_count() and not kwargs.get('instance'): 
       kwargs['instance'] = self.get_queryset()[i] 
      return super(BaseModelFormSet, self)._construct_form(i, **kwargs) 
     return super(BaseRatingFormSet, self)._construct_form(i, **kwargs) 

RatingFormSet = inlineformset_factory(
    Product, Rating, 
    can_delete=False, 
    max_num=0, 
    formset=BaseRatingFormSet, 
) 

編輯:條件必須在LEFT JOIN中完成,而不是在WHERE中完成,否則你將失去行。