Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/353.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 具有不同模型查询集的InlineFormSet_Python_Django_Forms_Django Admin_Django Forms - Fatal编程技术网

Python 具有不同模型查询集的InlineFormSet

Python 具有不同模型查询集的InlineFormSet,python,django,forms,django-admin,django-forms,Python,Django,Forms,Django Admin,Django Forms,我们要做的是使用不同模型的一些查询集,用初始值填充一个内联表单列表。我们有产品、指标、某些类别或类型或评级,以及一个评级,用于存储实际评级并将指标与产品联系起来 class Product(models.Model): name = models.CharField(max_length=100) price = models.IntegerField(max_length=6) class Metric(models.Model): name = models.Cha

我们要做的是使用不同模型的一些查询集,用初始值填充一个内联表单列表。我们有产品、指标、某些类别或类型或评级,以及一个评级,用于存储实际评级并将指标与产品联系起来

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中的所有表单和表单集代码,希望找到一个简单的解决方案:

他只是重写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,
)
编辑:条件必须在左连接中完成,而不是在何处,否则将丢失行