python – Django很多很多和管理员

python – Django很多很多和管理员,第1张

概述我有一个 django ap,它有一个相当复杂的模型设置.我最终使用多级合成来创建分层模型.所有的关系是一对一的,所以我可以使用继承,但我选择不这样做,我将从我的模型的对象组成中受益,这意味着我可以做类似的事情 product.outerframe.top.cost 这使得我必须进行复杂的计算,组织得更好. 但是,这种模式安排使得使用django admin很棘手.我基本上有一个直通表,即外框表只 @H_404_0@ @H_404_0@ 我有一个 django ap,它有一个相当复杂的模型设置.我最终使用多级合成来创建分层模型.所有的关系是一对一的,所以我可以使用继承,但我选择不这样做,我将从我的模型的对象组成中受益,这意味着我可以做类似的事情

product.outerframe.top.cost

这使得我必须进行复杂的计算,组织得更好.

但是,这种模式安排使得使用django admin很棘手.我基本上有一个直通表,即外框表只是一堆外键到其他表(每个表都有唯一约束).我最终了解了Modeladmin的add_vIEw()和change_vIEw()方法,这非常困难.

使用django管理员时,是否有更简单的方法来处理多对多/通过表格?

表格的排列方式如下:

产品>外框,内框,玻璃,其他

外框>顶部,底部,侧面等

内框架>顶部,侧面等

玻璃> glass_type等

其他>配件等

这是我的模特:

class Product(mixins.Productvariables):    name = models.CharFIEld(max_length=255)    sku = models.CharFIEld(max_length=100,unique=True,db_index=True)    image = thumbnail.ImageFIEld(upload_to='product_images',blank=True)    description = models.TextFIEld(blank=True)    group = models.ForeignKey('ProductGroup',related_name='products',null=True)    hIDden = models.BooleanFIEld(default=False)    product_specific_mark_up = models.DecimalFIEld(default=1.0,max_digits=5,decimal_places=2)    # Methods for totals    def total_material_cost(self,wIDth,height,options):        return sum([            self.outerframe.cost(wIDth,options),self.innerframe.cost(wIDth,self.glass.cost(wIDth,self.other.cost(wIDth,])    def total_labour_time(self,options):        return sum([            self.outerframe.labour_time(wIDth,self.innerframe.labour_time(wIDth,self.glass.labour_time(wIDth,self.other.labour_time(wIDth,])    def total_co2_output(self,options):        return sum([            self.outerframe.co2_output(wIDth,self.innerframe.co2_output(wIDth,self.glass.co2_output(wIDth,self.other.co2_output(wIDth,])    @property    def max_overall_wIDth(self):        return 1000    @property    def max_overall_height(self):        return 1000    def __unicode__(self):        return self.nameclass OuterFrame(models.Model,mixins.GetFIEldsMixin,mixins.GetRelatedClassesMixin):    top = models.OnetoOneFIEld(mixins.topFrame)    bottom = models.OnetoOneFIEld(mixins.BottomFrame)    sIDe = models.OnetoOneFIEld(mixins.SIDeFrame)    accessorIEs = models.OnetoOneFIEld(mixins.AccessorIEs)    flashing = models.OnetoOneFIEld(mixins.Flashing)    silicone = models.OnetoOneFIEld(mixins.Silicone)    product = models.OnetoOneFIEld(Product)    def cost(self,options):        #accessorIEs_cost = (self.accessorIEs.cost if options['accessorIEs'] else 0)        #flashing_cost = (self.flashing.cost if options['flashing'] else 0)        #silicone_cost = (self.silicone.cost if options['silicone'] else 0)        return sum([            self.top.cost * (wIDth / 1000),self.bottom.cost * (wIDth / 1000),self.sIDe.cost * (wIDth*2 / 1000),#accessorIEs_cost,#flashing_cost,#silicone_cost,])    def labour_time(self,options):        return datetime.timedelta(minutes=100)    def CO2_output(self,options):        return 100 # some kg measurement    @classmethod    def get_fIElds(cls):        options = cls._Meta        fIElds = {}        for fIEld in options.fIElds:            if fIEld.name == 'product':                continue            if isinstance(fIEld,models.OnetoOneFIEld):                related_cls = fIEld.rel.to                related_fIElds = fIElds_for_model(related_cls,fIElds=related_cls.get_fIElds())                fIElds.update( { related_cls.__name__ + '_' + name:fIEld for name,fIEld in related_fIElds.iteritems() })        return fIEldsclass InnerFrame(models.Model,mixins.GetRelatedClassesMixin):    top = models.OnetoOneFIEld(mixins.topFrame)    bottom = models.OnetoOneFIEld(mixins.BottomFrame)    sIDe = models.OnetoOneFIEld(mixins.SIDeFrame)    accessorIEs = models.OnetoOneFIEld(mixins.AccessorIEs)    product = models.OnetoOneFIEld(Product)    def cost(self,options):        #accessorIEs_cost = (self.accessorIEs.cost if options['accessorIEs'] else 0)        print self.top.cost        return sum([            self.top.cost * (wIDth / 1000),#    accessorIEs_cost,options):        return 100 # some kg measurementclass Glass(models.Model,mixins.GetRelatedClassesMixin):    glass_type_a = models.OnetoOneFIEld(mixins.GlasstypeA)    glass_type_b = models.OnetoOneFIEld(mixins.GlasstypeB)    enhanced = models.OnetoOneFIEld(mixins.Enhanced)    laminate = models.OnetoOneFIEld(mixins.Laminate)    low_iron = models.OnetoOneFIEld(mixins.LowIron)    privacy = models.OnetoOneFIEld(mixins.Privacy)    anti_slip = models.OnetoOneFIEld(mixins.AntiSlip)    heat_film_mirror = models.OnetoOneFIEld(mixins.HeatMirrorFIEld)    posished_edges = models.OnetoOneFIEld(mixins.PolishedEdges)    product = models.OnetoOneFIEld(Product)    def cost(self,options):        return sum([        ])    def labour_time(self,options):        return 100 # some kg measurementclass Other(models.Model,mixins.GetRelatedClassesMixin):    num_packages = models.OnetoOneFIEld(mixins.NumberPackages)    product = models.OnetoOneFIEld(Product)    def cost(self,options):        return 100    def labour_time(self,options):        return 100 # some kg measurement

混入:

class TimeCostMixin(models.Model,GetFIEldsMixin):    cost = models.DecimalFIEld(default=0.0,max_digits=10,decimal_places=2)    time = models.TimeFIEld(default=datetime.timedelta(0))    class Meta:        abstract = True##### Frame #####class FrameComponentMixin(TimeCostMixin):    external_wIDth = models.IntegerFIEld(default=0)    material_weight = models.DecimalFIEld(default=0.0,decimal_places=2)    u_value = models.DecimalFIEld(default=0.0,decimal_places=2)    class Meta:        abstract = Trueclass topFrame(FrameComponentMixin):    passclass BottomFrame(FrameComponentMixin):    passclass SIDeFrame(FrameComponentMixin):    passclass AccessorIEs(TimeCostMixin):    material_weight = models.DecimalFIEld(default=0.0,decimal_places=2)class Flashing(TimeCostMixin):    passclass Silicone(TimeCostMixin):    labour_time = models.DecimalFIEld(default=0.0,decimal_places=2)###################### Glass #####class GlasstypeA(TimeCostMixin):    material_weight = models.DecimalFIEld(default=0.0,decimal_places=2)class GlasstypeB(TimeCostMixin):    material_weight = models.DecimalFIEld(default=0.0,decimal_places=2)class Enhanced(TimeCostMixin):    material_weight = models.DecimalFIEld(default=0.0,decimal_places=2)class Laminate(TimeCostMixin):    material_weight = models.DecimalFIEld(default=0.0,decimal_places=2)class LowIron(TimeCostMixin):    passclass Privacy(TimeCostMixin):    passclass AntiSlip(TimeCostMixin):    passclass HeatMirrorFIEld(TimeCostMixin):    u_value = models.DecimalFIEld(default=0.0,decimal_places=2)class PolishedEdges(models.Model):    cost = models.DecimalFIEld(default=0.0,decimal_places=2)####################### other  #####class NumberPackages(models.Model):    number_of_packages = models.IntegerFIEld(default=0)##################

还有一个拉头管理员!

class Productadmin(adminImageMixin,admin.Modeladmin):    inlines = [ProductDownloadInline,ProductConfigurationInline]    add_form_template = 'admin/products/add_form.HTML'    change_form_template = 'admin/products/add_form.HTML'    @csrf_protect_m    @transaction.atomic    def add_vIEw(self,request,form_url='',extra_context=None):        extra_context = extra_context or {}        "The 'add' admin vIEw for this model."        model = self.model        opts = model._Meta        if not self.has_add_permission(request):            raise PermissionDenIEd        ModelForm = self.get_form(request)        formsets = []        inline_instances = self.get_inline_instances(request,None)        if request.method == 'POST':            form = ModelForm(request.POST,request.fileS)            if form.is_valID():                new_object = self.save_form(request,form,change=False)                form_valIDated = True            else:                form_valIDated = False                new_object = self.model()            prefixes = {}            for FormSet,inline in zip(self.get_formsets(request),inline_instances):                prefix = FormSet.get_default_prefix()                prefixes[prefix] = prefixes.get(prefix,0) + 1                if prefixes[prefix] != 1 or not prefix:                    prefix = "%s-%s" % (prefix,prefixes[prefix])                formset = FormSet(data=request.POST,files=request.fileS,instance=new_object,save_as_new="_saveasnew" in request.POST,prefix=prefix,queryset=inline.get_queryset(request))                formsets.append(formset)            #####            outer_frame_forms = [                modelform_factory(cls)(request.POST,prefix='OuterFrame_'+cls.__name__)                for cls in models.OuterFrame.get_related_classes(exclude=['product'])            ]            inner_frame_forms = [                modelform_factory(cls)(request.POST,prefix='InnerFrame'+cls.__name__)                for cls in models.InnerFrame.get_related_classes(exclude=['product'])            ]            glass_forms = [                modelform_factory(cls)(request.POST,prefix='InnerFrame'+cls.__name__)                for cls in models.Glass.get_related_classes(exclude=['product'])            ]            other_forms = [                modelform_factory(cls)(request.POST,prefix='InnerFrame'+cls.__name__)                for cls in models.Other.get_related_classes(exclude=['product'])            ]            #####            if all_valID(formsets                        +outer_frame_forms                        +inner_frame_forms                        +glass_forms                        +other_forms                        ) and form_valIDated:                self.save_model(request,new_object,False)                self.save_related(request,formsets,False)                self.log_addition(request,new_object)                ##### save object hIErichy #####                # inner frame                inner_frame = models.InnerFrame()                inner_frame.product = new_object                mapPing = {f.rel.to:f.name for f in models.InnerFrame._Meta.fIElds if f.name not in ['ID','product']}                for f in inner_frame_forms:                    obj = f.save()                    setattr(inner_frame,mapPing[obj.__class__],obj)                inner_frame.save()                # outer frame                outer_frame = models.OuterFrame()                outer_frame.product = new_object                mapPing = {f.rel.to:f.name for f in models.OuterFrame._Meta.fIElds if f.name not in ['ID','product']}                for f in outer_frame_forms:                    obj = f.save()                    setattr(outer_frame,obj)                outer_frame.save()                # glass                glass = models.Glass()                glass.product = new_object                mapPing = {f.rel.to:f.name for f in models.Glass._Meta.fIElds if f.name not in ['ID','product']}                for f in glass_forms:                    obj = f.save()                    setattr(glass,obj)                glass.save()                # other                other = models.Other()                other.product = new_object                mapPing = {f.rel.to:f.name for f in models.Other._Meta.fIElds if f.name not in ['ID','product']}                for f in other_forms:                    obj = f.save()                    setattr(other,obj)                other.save()                #################################                return self.response_add(request,new_object)        else:            forms = SortedDict({})            forms['Outer Frame Variables'] = {                cls.__name__: modelform_factory(cls)(prefix='OuterFrame_'+cls.__name__)                for cls in models.OuterFrame.get_related_classes(exclude=['product'])            }            forms['Inner Frame Variables'] = {                cls.__name__: modelform_factory(cls)(prefix='InnerFrame'+cls.__name__)                for cls in models.InnerFrame.get_related_classes(exclude=['product'])            }            forms['Glass Variables'] = {                cls.__name__: modelform_factory(cls)(prefix='InnerFrame'+cls.__name__)                for cls in models.Glass.get_related_classes(exclude=['product'])            }            forms['Other Variables'] = {                cls.__name__: modelform_factory(cls)(prefix='InnerFrame'+cls.__name__)                for cls in models.Other.get_related_classes(exclude=['product'])            }            extra_context['forms'] = forms            # Prepare the dict of initial data from the request.            # We have to special-case M2Ms as a List of comma-separated PKs.            initial = dict(request.GET.items())            for k in initial:                try:                    f = opts.get_fIEld(k)                except models.FIEldDoesNotExist:                    continue                if isinstance(f,models.ManyToManyFIEld):                    initial[k] = initial[k].split(",")            form = ModelForm(initial=initial)            prefixes = {}            for FormSet,prefixes[prefix])                formset = FormSet(instance=self.model(),queryset=inline.get_queryset(request))                formsets.append(formset)        adminForm = helpers.adminForm(form,List(self.get_fIEldsets(request)),self.get_prepopulated_fIElds(request),self.get_Readonly_fIElds(request),model_admin=self)        media = self.media + adminForm.media        inline_admin_formsets = []        for inline,formset in zip(inline_instances,formsets):            fIEldsets = List(inline.get_fIEldsets(request))            Readonly = List(inline.get_Readonly_fIElds(request))            prepopulated = dict(inline.get_prepopulated_fIElds(request))            inline_admin_formset = helpers.InlineadminFormSet(inline,formset,fIEldsets,prepopulated,Readonly,model_admin=self)            inline_admin_formsets.append(inline_admin_formset)            media = media + inline_admin_formset.media        context = {            'Title': _('Add %s') % force_text(opts.verbose_name),'adminform': adminForm,'is_popup': IS_POPUP_VAR in request.REQUEST,'media': media,'inline_admin_formsets': inline_admin_formsets,'errors': helpers.adminerrorList(form,formsets),'app_label': opts.app_label,'preserved_filters': self.get_preserved_filters(request),}        context.update(extra_context or {})        return self.render_change_form(request,context,form_url=form_url,add=True)
解决方法 我没有完全处理你冗长的add_vIEw方法,但你的一般问题的答案只是“不”.管理员没有提供任何处理多层异构层次结构的好方法.通过内联很好地处理两层层次结构,因此您可以轻松地进行处理,以便通过编辑任何一层中的对象,您可以方便地管理下一层中的相关对象;但除此之外没什么.

多年来一直有a ticket开放为管理员添加嵌套内联支持,这将有助于处理这种情况.但是有许多棘手的边缘情况,并且很难使UI易于理解,因此补丁从未达到提交就绪状态.

在某些时候,您的数据模型的复杂性超出了通用管理界面可以处理的良好可用性,并且您最好只编写自己的自定义管理界面.主要是管理员只是建立在ModelForms和InlineModelFormsets之上,所以它并不像你想象的那样难以构建你自己的工作方式;与尝试大量定制管理员相比,它通常更容易(并且具有更好的结果).

我还应该提一下,通过表可以使用admin inlines多对多(即使through表是隐式的,而不是它自己的模型类),因为如何访问隐式创建的直通模型并不是很明显:

class MyM2MInline(admin.TabularInline):    model = SomeModel.m2m_fIEld.through

@H_404_0@ 总结

以上是内存溢出为你收集整理的python – Django很多很多和管理员全部内容,希望文章能够帮你解决python – Django很多很多和管理员所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/langs/1197113.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-03
下一篇 2022-06-03

发表评论

登录后才能评论

评论列表(0条)

保存