2017-10-17 6 views
0

を更新しようとしたとき、私は、ヘッダ情報と合計を含む引用(マスター)、およびQuotationDetail(詳細)のシンプルなマスター/ディテールモデルを持っ含みます見積アイテムの場合、この子モデルはPriceLevel FKフィールドを使用して、個々のアイテムのマークアップを計算します。私は、管理者は一度に複数のアイテムにこのPriceLevelを変更できるようにDjangoの管理アクションを実装しようとしていますが、私はエラーを取得:PythonのDjangoの管理アクションで1.11「とValueError不完全な形式の」FKフィールド

[myProjectPath]\lib\site-packages\django\contrib\admin\options.py", line 812, in get_action_choices 
    choice = (name, description % model_format_dict(self.opts)) 
ValueError: incomplete format 

は、これは私のmodels.py(関連するモデル)です。

class NivelDePrecio(models.Model): # PriceLevel 
    # Fields 
    nombre = models.CharField(max_length=50) 
    slug = extension_fields.AutoSlugField(populate_from='nombre', blank=True) 
    valor = models.DecimalField(max_digits=7, decimal_places=4) 
    factor = models.DecimalField(max_digits=7, decimal_places=6, null=True, blank=True) 

    class Meta: 
     ordering = ('-valor',) 

    def __str__(self): 
     return self.nombre 

    def save(self, *args, **kwargs): 
     self.factor = 1/(1 - self.valor) 
     super(NivelDePrecio, self).save() 


class Cotizacion(models.Model): # Quotation (master) 
    # Fields 
    nombre = models.CharField(max_length=100) 
    slug = extension_fields.AutoSlugField(populate_from='nombre', blank=True, overwrite=True) 
    fecha_ida = models.DateField(default=date.today) 
    fecha_regreso = models.DateField(default=date.today) 

    # Relationship Fields 
    itinerario = models.ForeignKey(Itinerario, on_delete=CASCADE, verbose_name='itinerario') 
    nivel_de_precio = models.ForeignKey(NivelDePrecio, verbose_name='nivel de precio', 
             on_delete=models.PROTECT, null=True, blank=True) 

    class Meta: 
     ordering = ('itinerario__cliente__codigo', '-fecha_ida') 

    def __str__(self): 
     return str(self.nombre) 


class CotizacionDetalle(models.Model): # QuotationDetail (detail) 
    # Fields 
    descripcion = models.CharField(max_length=100, null=True, blank=True) 
    cantidad = models.DecimalField(max_digits=10, decimal_places=2) 
    costo = models.DecimalField(max_digits=10, decimal_places=2, default=0, editable=False) 
    monto = models.DecimalField(max_digits=10, decimal_places=2, default=0, editable=False) 
    markup = models.DecimalField(max_digits=6, decimal_places=4, default=0, editable=False) 
    utilidad = models.DecimalField(max_digits=6, decimal_places=4, default=0, editable=False) 
    total = models.DecimalField(max_digits=10, decimal_places=2, default=0, editable=False) 
    slug = extension_fields.AutoSlugField(populate_from='item', blank=True) 

    # Relationship Fields 
    cotizacion = models.ForeignKey(Cotizacion, on_delete=CASCADE, verbose_name='cotizacion', related_name='lineas') 
    item = models.ForeignKey(Item, verbose_name='item', related_name='item') 
    nivel_de_precio = models.ForeignKey(NivelDePrecio, verbose_name='nivel de precio', 
             on_delete=models.PROTECT, null=True, blank=True) 

    class Meta: 
     ordering = ('id',) 

    def save(self, *args, **kwargs): 
     self.descripcion = self.item.descripcion_venta 
     self.costo = self.item.costo 
     self.monto = self.cantidad * self.costo 
     if self.nivel_de_precio is None: 
      self.nivel_de_precio = self.cotizacion.nivel_de_precio 
     self.markup = Decimal(round(self.nivel_de_precio.factor - 1, 4)).quantize(Decimal("0.0000")) 
     self.utilidad = Decimal(self.nivel_de_precio.valor).quantize(Decimal("0.0000")) 
     self.total = Decimal(self.monto) * (1 + Decimal(self.markup)) 
     super(CotizacionDetalle, self).save(*args, **kwargs) 

    def __str__(self): 
     return str(self.descripcion) 

これは私のadmin.pyです(私も同じ結果の誤りを持つアクションのコメントバージョンを試してみました)。この変更のオプションをFKモデルから選択できるのはうれしいことですが、マークアップ値を0.05%増やし、もう1つはマークアップを0.05%減らすという2つのアクションを実行することで動作するようにします。その場合、代わりにマークアップフィールドを更新する必要があります。私admin.py

def create_action_nivel(nivel): 
    def action(modeladmin, request, queryset): 
     queryset.update(nivel_de_precio=nivel) 

    name = "change_to_%s" % (nivel.slug,) 
    return (name, (action, name, "Cambiar Nivel de Precio a: %s" % (nivel,))) 

...

で次のように

https://djangosnippets.org/snippets/1836/

class CotizacionDetalleAdminForm(forms.ModelForm): 
    class Meta: 
     model = CotizacionDetalle 
     fields = ['item', 'cotizacion', 'cantidad', 'nivel_de_precio'] 


def cambiar_utilidad(modeladmin, request, queryset): 
    from .models import NivelDePrecio 
    ndp = NivelDePrecio.objects.get(id=5) 
    queryset.update(nivel_de_precio_id=ndp.id) 
    # for cd in queryset: 
    #  cd.nivel_de_precio_id = ndp.id 
    #  cd.save() 


cambiar_utilidad.short_description = "Cambiar Utilidad 25%" 


class CotizacionDetalleAdmin(admin.ModelAdmin): 
    # save_as = True 
    form = CotizacionDetalleAdminForm 
    list_display = ['cliente', 'itinerario', 'cotizacion', 'descripcion', 
        'cantidad', 'costo', 'monto', 'utilidad', 'markup', 'total'] 
    list_display_links = ['descripcion'] 
    readonly_fields = ['descripcion', 'costo', 'monto', 'utilidad', 'markup', 'total', 'slug', 'creado', 'actualizado'] 
    search_fields = ['descripcion'] 
    list_filter = (('cotizacion__itinerario__cliente', DropdownFilterRelated), 
        ('cotizacion__itinerario', DropdownFilterRelated), 
        ('cotizacion', DropdownFilterRelated),) 
    ordering = ['cotizacion__itinerario__cliente__codigo', 'cotizacion__fecha_ida', 'id'] 
    actions = [cambiar_utilidad] 


admin.site.register(CotizacionDetalle, CotizacionDetalleAdmin) 

更新:

は...これを試してみました

class CotizacionDetalleAdmin(admin.ModelAdmin): 

    def get_actions(self, request): 
     return dict(create_action_nivel(n) for n in NivelDePrecio.objects.all()) 

しかし、私は同じエラーを取得するには、トレースバックは、ここに示す:フィールドを更新するときhttp://dpaste.com/360GEJY

同じスニペットは、外部キー・フィールドないだけで正常に動作します。私は別のモデルでそれを使用し、うまく動作します:

def create_action_estatus(estatus): 
    def action(modeladmin, request, queryset): 
     queryset.update(estatus=estatus) 

    name = "mark_%s" % (estatus,) 
    return name, (action, name, "Cambiar Estatus: %s " % (estatus,)) 


class ItinerarioAdmin(admin.ModelAdmin): 
    def get_actions(self, request): 
     statuses= [ "Solicitado", "Cotizado", "Confirmado", "Facturado", "Cerrado"] 
     return dict(create_action_estatus(e) for e in statuses) 

答えて

0

私は、多くの裁判の後、問題が説明フィールドの内容を内部シンボルの使用である、エラーを検出しました明らかに作成時 管理アクションを動的にshort_description生成された文字列が再使用され、内部に%記号がある場合は、不完全な形式のエラーがスローされます。 (エスケープ)ダブル%記号

の点に注意してください...

cambiar_nivel.short_description = "Cambiar Nivel de Precio a {0:.1f}%%".format(nivel.valor * 100) 

ソリューションは、このようなSHORT_DESCRIPTION文字列を作成することでした

関連する問題