Python 需要在Django中保存估算模型

Python 需要在Django中保存估算模型,python,django,Python,Django,我在Django中有以下models.py和admin.py文件。我想做两件事 合并Environment和ItemObject的specs字段,并将其存储到Environment的specs中,这是我之所以能够做到的,因为我能够找到放置逻辑的位置。(class AddEnvironmentDetailsInlineForm(forms.ModelForm)) 我需要做同样的估计。我需要获取Environment.specs和Estimate.specs,将两者合并并保存在Estimate.sp

我在Django中有以下models.py和admin.py文件。我想做两件事

  • 合并Environment和ItemObject的specs字段,并将其存储到Environment的specs中,这是我之所以能够做到的,因为我能够找到放置逻辑的位置。(
    class AddEnvironmentDetailsInlineForm(forms.ModelForm)
  • 我需要做同样的估计。我需要获取Environment.specs和Estimate.specs,将两者合并并保存在Estimate.specs中
  • 合并类似于ItemObject->Environment->Estimate

    挑战在于,我无法找出将该逻辑用于估算和环境的位置。我是否需要为Estimate创建一个模型表单以实现合并?我不清楚文件的逻辑(我还在学习Django中的概念)。如果有人能让我明白,那就太好了

    models.py

    class Estimate(CommonModel):
       ...
    
    class Environment(CommonModel):
    
        estimate = models.ForeignKey(Estimate,related_name='environments')
        logic = PythonCodeField(blank=True, null=True)
    
        ...
    
    class Item(CommonModel):
       ...
    
    class ItemTemplate(Item):
        pass
    
    class ItemObject(Item):
        pass
    
    class EnvironmentDetail(models.Model):
        environment = models.ForeignKey(Environment)
        item_name = models.CharField(max_length=200,blank=True)
        qty = models.FloatField('Qty')
        ...
    
    管理员

    class CommonAdmin(admin.ModelAdmin):
        ...
    
    class EnvironmentInlineAdmin (admin.TabularInline):
    
        model = Environment
        ...
        formfield_overrides = {
            JSONField:{ 'widget':JSONEditor },
        }
    
        ...
    
        def save_model(self, request, obj, *kwargs):
            if request.user.is_superuser or request.user==obj.author:
                obj.author.id=request.user.id
                super(EnvironmentInlineAdmin,self).save_model(request, obj, *kwargs)
            else:
                raise ValidationError("author must be you")   
    
    
    class EstimateAdmin (CommonAdmin):
        inlines = [ EnvironmentInlineAdmin ]
        list_display = ('title', 'gp_code', 'otc_price','annual_price')
    
    admin.site.register(Estimate,EstimateAdmin)
    
    class EnvironmentDetailsInlineForm(forms.ModelForm):
        class Meta:
            model = EnvironmentDetail
            fields = ['item_name','qty']
    
        show_change_link = True
    
    class AddEnvironmentDetailsInlineForm(forms.ModelForm):
        class Meta:
            model = EnvironmentDetail
            fields = ['item_name','item', 'qty']
        item = forms.ModelChoiceField(queryset=ItemTemplate.objects.all())
    
        def clean(self):
            instance = self.cleaned_data['item'] 
            item_specs = self.cleaned_data['item'].specs
            environment_specs = self.cleaned_data['environment'].specs
            environment_specs.update(item_specs)
            fields = [f.name for f in Item._meta.fields]
            values = dict( [(x, getattr(instance, x)) for x in fields] )
            new_instance = ItemObject(**values)
            new_instance.save()  #save new one
    
            #instance.delete() # remove the old one
            self.cleaned_data['item'] = new_instance
    
            return self.cleaned_data  # Return self.cleaned_data at the end of clean() 
    
        def save_model(self, request, obj, *kwargs):
            if request.user.is_superuser or request.user==obj.author:
                super(AddEnvironmentDetailsInlineForm,self).save_model(request, obj, *kwargs)
            else:
                raise ValidationError("author must be you")   
    
    class EnvironmentDetailsInlineAdmin (admin.TabularInline):
    
        model = EnvironmentDetail
        ...
        form = EnvironmentDetailsInlineForm
    
        formfield_overrides = {
            JSONField:{ 'widget':JSONEditor },
        }
    
    
        def change_link(self, obj):
            return mark_safe('<a href="%s">Edit Item</a>' % \
                            reverse('admin:estimate_itemobject_change',
                            args=(obj.item.id,)))
    
        def item_type(self, obj):
            return  obj.item.item_type
    
        ...
    
    class AddEnvironmentDetailsInlineAdmin (admin.TabularInline):
    
        model = EnvironmentDetail
        fields = ('item_name','item', 'qty', )
        form = AddEnvironmentDetailsInlineForm
    
        def has_change_permission(self, request, obj=None):
            return False
        def item(self,obj):
            return  ItemTemplate
    
    class EnvironmentAdmin (CommonAdmin):
    
        model=Environment
        save_as = True
        inlines = [ EnvironmentDetailsInlineAdmin,AddEnvironmentDetailsInlineAdmin]
        ...
    
        def get_model_perms(self, request):
            """
            Return empty perms dict thus hiding the model from admin index.
            """
            return {}
    
    admin.site.register(Environment,EnvironmentAdmin)
    

    与您的问题相比,您的代码非常大。我减少了一点代码。添加了它们,这样如果有人问,它就会在那里。正如我从你的问题中了解到的,你想在一个下拉列表中从两个模型中获取数据吗?不。你看,当估计值注册时,它也有环境。环境将具有字段(例如,规范,它是一个字典)。Estimate还有specs字段,它也是一个字典。我想知道把逻辑放在哪里,这样我就可以把两者合并。因此,当我保存模型时,估计值的规格会更新。我认为您需要信号来解决您的问题,它有两种风格:pre和post,顾名思义,它们在保存数据之前和保存数据之后工作。您在最后阶段需要的数据可以通过查询进行合并,但场景可以通过django中的信号进行处理
    @receiver(post_save, sender=Estimate)
    
    def update_specs_estimate(sender, instance, **kwargs):
        print("instance", instance.specs)
        return instance.specs
    
    @receiver(post_save, sender=Environment)
    def take_specs_environment(sender, instance, **kwargs):
        print("instance", instance.specs)
        return instance.specs
    
    def dict_merge(update_specs_estimate, take_specs_environment):
    
        return (update_specs_estimate.update(take_specs_environment))