【问题标题】:Django: include a primary key field in an M2M inline recordDjango:在 M2M 内联记录中包含主键字段
【发布时间】:2014-05-02 17:32:08
【问题描述】:

我有一个 Product 模型,其中包含对 Option 模型的 M2M 引用,它使用中间模型 OptionPrice,它允许我用特定于产品的值覆盖选项的基本值。

这是三个模型:

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class Product(models.Model):
    productid = UUIDField(db_column='ProductID', editable=False, primary_key=True, auto=True, hyphenate=True) 
    productname = models.CharField(db_column='ProductName', max_length=100, verbose_name='name', default='') 
    slug = AutoSlugField(populate_from='productname',unique=True, max_length=100, always_update=True)
    productnumber = models.CharField(db_column='ProductNumber', blank=True, max_length=50, null=True, verbose_name='number', default='') 
    cost = models.DecimalField(decimal_places=4, max_digits=19, db_column='Cost', default=0) 
    priceperitem = models.DecimalField(decimal_places=4, max_digits=19, db_column='PricePerItem', verbose_name='price per item', default=0) 
    onspecial = models.BooleanField(db_column='OnSpecial', verbose_name='on special', default=False) 
    discount = models.FloatField(null=True, db_column='Discount', blank=True, verbose_name='discounted', default=0) 

    #connections to other models
    options = models.ManyToManyField(Option, null=True, through='OptionPrice', verbose_name='product options', blank=True) 
    optiongroups = models.ManyToManyField(OptionGroup, null=True, verbose_name='product option groups', blank=True) 

    package = models.ForeignKey(ShippingPackage, verbose_name='shipping container', default=1) 
    categories = models.ManyToManyField(Category, verbose_name='product categories') 
    cross_sell = models.ManyToManyField('Product', verbose_name='cross-sell items', blank=True) 


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class Option(models.Model):
    optionid = UUIDField(db_column='OptionID', editable=False, primary_key=True, auto=True, hyphenate=True) 
    title = models.CharField(db_column='Title', max_length=500) 
    price = models.DecimalField(decimal_places=4, max_digits=19, db_column='Price') 
    pricemodstyle = models.CharField(db_column='PriceModStyle', max_length=50, verbose_name='price modification style', choices=PRICE_MOD_CHOICES) 
    displayrank = models.IntegerField(db_column='DisplayRank', verbose_name='sort order') 
    optiongroup = models.ForeignKey('OptionGroup', verbose_name='option group') 



#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class OptionPrice(models.Model):
    optionpriceid = UUIDField(db_column='OptionPriceID', editable=False, primary_key=True, auto=True, hyphenate=True) 
    option = models.ForeignKey(Option)
    product = models.ForeignKey(Product)
    price = models.DecimalField(decimal_places=4, max_digits=19, db_column='Price') 
    pricemodstyle = models.CharField(db_column='PriceModStyle', max_length=50, verbose_name='price modification style', choices=PRICE_MOD_CHOICES) 

,对于 admin.py,我将产品选项定义为内联

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class ProductAdmin(ImportExportModelAdmin):
    resource_class = ProductResource
    model=Product
    ordering = ['categories__categoryname','productname']
    save_on_top = True
    save_as = True
    inlines = [OptionPriceAdminInline]

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class OptionPriceAdminInline(admin.TabularInline):
    model=OptionPrice
    extra = 0
    save_on_top = True

我的问题是,当我在管理员中加载产品时,内联显示得很漂亮,除了主键之外的每个字段都表示(optionpriceid)。因此,当我第一次向该产品添加选项时,它们会正确保存(新 ID 是自动创建的)。如果我随后尝试重新加载产品并编辑保存的选项,我会收到 MultiValueDictKeyError,因为这些内联项目实际上并没有将它们的主键值包含在管理员发出的行中。

我做错了什么?

【问题讨论】:

    标签: python django django-admin many-to-many


    【解决方案1】:

    问题原来是django bug,由this pull request 解决。问题是我使用自定义 UUIDField 作为主键 - 引用票:

    似乎这个问题发生在具有不基于 AutoField 的主键字段的模型(例如 CharField)。

    当主键字段不基于AutoField时,'has_auto_field'不设置为True,因此不会在表单中输出主键。

    【讨论】:

      猜你喜欢
      • 2010-11-30
      • 1970-01-01
      • 2014-01-02
      • 1970-01-01
      • 1970-01-01
      • 2013-02-05
      • 1970-01-01
      • 2015-09-28
      • 2012-01-09
      相关资源
      最近更新 更多