簡體   English   中英

具有不同模型的queryset的InlineFormSet

[英]InlineFormSet with queryset of different model

我們正在嘗試使用不同模型的某些查詢集填充具有初始值的內聯表單列表。 我們有產品,指標(某些類別,類型或等級)和等級,其中存儲了實際的等級並將指標與產品聯系起來。

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

有一些替代。 有任何想法嗎?

您在尋找管理員還是前端解決方案? 管理員的方法如下,您可以對其進行反向工程以獲得類似的前端解決方案:

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

我設法實現了類似的功能,如下所示:

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

編輯:條件必須在左聯接中完成,而不是在WHERE中完成,否則您將缺少行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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