在另一个中显示表单

时间:2016-05-30 06:17:51

标签: python django

我想在另一种表单中显示一个表单。

例如我有这些模型:

class Measure(models.Model):

    length = models.ForeignKey(Statistics, related_name='Length', null=True, blank=True)
    surface_area = models.ForeignKey(Statistics, related_name='Surface area+', null=True, blank=True)
    section_area = models.ForeignKey(Statistics, related_name='Section area+', null=True, blank=True)
    volume = models.ForeignKey(Statistics, related_name='Volume', null=True, blank=True)
    diameter = models.ForeignKey(Statistics, related_name='Diameter', null=True, blank=True)


class Statistics(models.Model):
    total = models.FloatField('Total', null=True, blank=True)
    avg = models.FloatField('Average', null=True, blank=True)
    min = models.FloatField('Minimum', null=True, blank=True)
    max = models.FloatField('Maximum', null=True, blank=True)
    standard_deviation = models.FloatField('Standard deviation', null=True, blank=True)

然后我将这些表格与之前的模型相对应:

class StatisticsForm(forms.ModelForm):
    class Meta:
        model = Statistics
        fields = '__all__'

class MeasureForm(forms.ModelForm):
    class Meta:
        model = Measure
        fields = '__all__'

        # Here I have to say that the right form for each field is the StatisticForm

表单中的ForeignKey呈现为一个组合框,包括另一个表中的所有对象(在我的情况下是Statistics表),我想用一个StatisticsForm对象替换组合框,这样我就可以控制方式了渲染统计对象

非常感谢。

1 个答案:

答案 0 :(得分:2)

您的数据库方案和模型设计不正确,无法解决手头的问题。你正在定义一个"有很多"关系在错误的方向。一个Measurement应该有多个Statistics,但是一个Statistics不应该有多个Measurement

由于您的模型现在已设置,ForeignKey位于关系的错误一侧。你应该这样做:

class Measure(models.Model):
    def save(self,*args,**kwargs):
        result = super(Measure, self).save(*args,**kwargs)
        Statistics.objects.create(name='length', measurement=self)
        Statistics.objects.create(name='section', measurement=self)
        Statistics.objects.create(name='surface', measurement=self)
        Statistics.objects.create(name='volume', measurement=self)
        Statistics.objects.create(name='diameter', measurement=self)
        return result

要像访问当前代码一样Statistics访问Measurement,您可以添加几个@property个快捷方式:

class Measure(models.Model):
    @property
    def length(self):
        return self.statistics_set.get(name='length')
    @property
    def section(self):
        return self.statistics_set.get(name='section')
    @property
    def surface(self):
        return self.statistics_set.get(name='surface')
    @property
    def volume(self):
        return self.statistics_set.get(name='volume')
    @property
    def diameter(self):
        return self.statistics_set.get(name='diameter')

class Statistics(models.Model):
    name = models.CharField(max_length=10)
    measurement = models.ForeignKey('Measurement')
    total = models.FloatField('Total', null=True, blank=True)
    avg = models.FloatField('Average', null=True, blank=True)
    min = models.FloatField('Minimum', null=True, blank=True)
    max = models.FloatField('Maximum', null=True, blank=True)
    standard_deviation = models.FloatField('Standard deviation', null=True, blank=True)

一旦修复了对象之间的关系,问题就变得更容易解决了。 ForeignKeyFields不是形式中的Statistics,而是成为正确的相关对象,这些对象通常由django处理。

正如评论中提到的@solarisssmoke,您正在寻找表单集。以下是django documentation展示如何实现所需目标的示例:

有问题的模型:

class Author(models.Model):
    name = models.CharField(max_length=100)
    title = models.CharField(max_length=3, choices=TITLE_CHOICES)
    birth_date = models.DateField(blank=True, null=True)

    def __str__(self):              # __unicode__ on Python 2
        return self.name

class Book(models.Model):
    name = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)

使用inlineformset_factory创建所需的formset的视图:

from django.forms import inlineformset_factory


def manage_books(request, author_id):
    author = Author.objects.get(pk=author_id)
    BookInlineFormSet = inlineformset_factory(Author, Book, fields=('title',))
    if request.method == "POST":
        formset = BookInlineFormSet(request.POST, request.FILES, instance=author)
        if formset.is_valid():
            formset.save()
            # Do something. Should generally end with a redirect. For example:
            return HttpResponseRedirect(author.get_absolute_url())
    else:
        formset = BookInlineFormSet(instance=author)
    return render(request, 'manage_books.html', {'formset': formset})

如果性能成为一个问题,请查看prefetch_related以提高性能。