2009-08-12 6 views
1

다른 모델의 쿼리 집합을 사용하여 초기 값으로 인라인 양식 목록을 채우는 작업입니다. Google은 제품, 측정 항목 (일부 카테고리 또는 유형 또는 등급)과 등급을 제공하며 실제 등급 및 관계 통계를 제품에 저장합니다.다른 모델의 쿼리 집합을 사용하는 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 개의 평가가 페이지에 표시됩니다. 특정 제품/측정 항목 조합에 대한 등급이 아직 존재하지 않을 수 있으므로 등급을 기반으로 한 쿼리 세트를 사용하여 페이지를 채울 수 없습니다.

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

그는 단지 BaseInlineFormSet 뭔가를 무시하고 있습니다 : 우리는 모든 형태와 장고의 formset 코드를 찾아 봤는데,이만큼 간단한 해결책을 마련 바라고있다

그것을 인라인으로. 어쩌면 우리는 단지 비슷하게 만들 수 있습니다.

class RatingInlineFormset(BaseInlineFormset): 

일부 무시할 수 있습니다. 어떤 아이디어?

답변

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

편집 : 내가 관리해야

# 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

조금 같은 유사한 기능을 구현하려면 다음과 같이 관리 방법은 다음과 같다, 당신은 유사한 프런트 엔드 솔루션을 얻을 수를 리버스 엔지니어링 수 있었던 조건은 LEFT JOIN (LEFT JOIN)에서 수행해야하며, WHERE이 아닌 LEFT JOIN에서 수행해야합니다. 그렇지 않으면 누락 된 행이 생깁니다.