簡體   English   中英

Django 多對多關系

[英]Django ManyToMany relationship

models.py 中

from django.db import models
from django.utils.translation import ugettext as _

# Create your models here.
class Category(models.Model):
    name            = models.CharField(_(u"Name"), max_length=250)
    products        = models.ManyToManyField("Product", verbose_name=_(u"Products"), \
                      blank=True, null=True, related_name="+")
        
class Product(models.Model):
    name            = models.CharField(_(u"Name"), max_length=250)    
    category        = models.ManyToManyField("Category", verbose_name=_(u"Category"), \
                      blank=True, null=True, related_name="+")

在管理頁面:

m2m關系

問題:
如何設置models.pyproductscategory m2m 字段之間的關系,以便在管理頁面中,如圖所示, b2 (產品)被標記為屬於a2 (類別)。
歡迎就 [產品、類別] 的實施提出任何建議,謝謝。

聚苯乙烯
我是 Django 的新手。對不起我的英語。

問題是你有兩個 ManyToMany字段。 正如您所指出的那樣,當關系設置在其中一個中時,它就不在另一個中。

解決方案很簡單:刪除其中一個字段。 您只需要在關系的一側使用ManyToManyField。 Django讓您自動訪問另一方。 因此,如果您在Product型號上保留了categories字段,則可以執行my_product.categories.all()以獲取與產品相關聯的類別; my_category.product_set.all()獲取屬於某個類別的產品。

你還需要刪除related_name="+"屬性:你可能會把它放進去因為你遇到了沖突,這應該是一個線索。

2022 年 3 月更新:

Django中有兩種創建“多對多”關系的方法。 一個不使用“ManyToManyField()” ,一個使用“ManyToManyField()” 首先,我將向您展示不使用"ManyToManyField()"的方法。

<沒有“ManyToManyField()”的方法>

要創建多對多關系,必須有2 個其他表之間的中間表,並且它必須具有來自 2 個其他表的每個外鍵,並且這些外鍵必須是唯一的 因此,我在“Category”和“Product”表之間創建了中間表“CategoryProduct” ,它具有來自“Category”和“Product”表的每個外鍵這些外鍵是唯一的,如下所示。

“模型.py”

from django.db import models

class Category(models.Model):
    name = models.CharField(max_length=255)
    
    def __str__(self):
        return self.name

class Product(models.Model):
    name = models.CharField(max_length=255)    
    
    def __str__(self):
        return self.name

# The middle table between "Category" and "Product" tables
class CategoryProduct(models.Model): 
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    product = models.ForeignKey(Product, on_delete=models.CASCADE)

    class Meta:
        unique_together = [['category', 'product']]

這就是將中間表“CategoryProduct”內聯到“Product”表的方式,如下所示。

“管理員.py”

from django.contrib import admin
from .models import CategoryProduct, Product

class CategoryProductInline(admin.TabularInline):
    model = CategoryProduct
    min_num = 1 
    extra = 2
    max_num = 5

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    inlines = [CategoryProductInline]

這是它的樣子:

在此處輸入圖像描述

這就是將中間表“CategoryProduct”內聯到“Category”表的方式,如下所示。

“管理員.py”

from django.contrib import admin
from .models import CategoryProduct, Category

class CategoryProductInline(admin.TabularInline):
    model = CategoryProduct
    min_num = 1 # 1 required inline field displayed
    extra = 2   # 2 unrequired inline fields displayed
    max_num = 5 # 5 inline fields as a maximum

@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
    inlines = [CategoryProductInline]

這是它的樣子:

在此處輸入圖像描述

<使用“ManyToManyField()”的方法>

這是“ManyToManyField()”的方法,如下所示。 上面使用“ManyToManyField()”的方式和沒有使用 ManyToManyField()”的方式之間的區別是在這種情況下使用“ManyToManyField()”的方式,帶有 ManyToManyField()”“類別”字段被添加到“產品” “ class正如您在下面看到的,它們之間唯一的代碼不同,所以其他都是一樣的。

“模型.py”

from django.db import models

class Category(models.Model):
    name = models.CharField(max_length=255)

    def __str__(self):
        return self.name
    
class Product(models.Model):
    name = models.CharField(max_length=255)
    categories = models.ManyToManyField(
        Category, 
        through='CategoryProduct'
    ) # "categories" field is added

    def __str__(self):
        return self.name

class CategoryProduct(models.Model):
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    product = models.ForeignKey(Product, on_delete=models.CASCADE)

    class Meta:
        unique_together = [['category', 'product']]

您可以將帶有“ManyToManyField()”“產品”字段添加到“類別”class ,並且只有代碼不同,所以其他內容也相同。

“模型.py”

from django.db import models

class Product(models.Model):
    name = models.CharField(max_length=255)

    def __str__(self):
        return self.name

class Category(models.Model):
    name = models.CharField(max_length=255)
    products = models.ManyToManyField(
        Product, 
        through='CategoryProduct'
    ) # "products" field is added

    def __str__(self):
        return self.name

class CategoryProduct(models.Model):
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    product = models.ForeignKey(Product, on_delete=models.CASCADE)

    class Meta:
        unique_together = [['category', 'product']]

因此,將中間表“CategoryProduct”內聯到“Product”表的方式也與沒有“ManyToManyField()”的方式相同,如下所示。

“管理員.py”

from django.contrib import admin
from .models import CategoryProduct, Product

class CategoryProductInline(admin.TabularInline):
    model = CategoryProduct
    min_num = 1 
    extra = 2
    max_num = 5

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    inlines = [CategoryProductInline]

這是它的樣子:

在此處輸入圖像描述

並且,將中間表“CategoryProduct”內聯到“Category”表的方式與沒有“ManyToManyField()”的方式相同,如下所示。

“管理員.py”

from django.contrib import admin
from .models import CategoryProduct, Category

class CategoryProductInline(admin.TabularInline):
    model = CategoryProduct
    min_num = 1 # 1 required inline field displayed
    extra = 2   # 2 unrequired inline fields displayed
    max_num = 5 # 5 inline fields as a maximum

@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
    inlines = [CategoryProductInline]

這是它的樣子:

在此處輸入圖像描述

此外,當您使用“ManyToManyField()”時,您可以刪除可自定義的中間表“CategoryProduct”的代碼 在這種情況下,您刪除中間表“CategoryProduct”的代碼,隱式創建不可自定義的默認中間表 因此,我從“ManyToManyField()”中刪除了中間表“CategoryProduct”“through='CategoryProduct'”的代碼,如下所示。

“模型.py”

from django.db import models

class Category(models.Model):
    name = models.CharField(max_length=255)

    def __str__(self):
        return self.name

class Product(models.Model):
    name = models.CharField(max_length=255)
    categories = models.ManyToManyField(Category)
    categories = models.ManyToManyField(
        Category, 
        # through='CategoryProduct'
    )

    def __str__(self):
        return self.name

# class CategoryProduct(models.Model):
#     category = models.ForeignKey(Category, on_delete=models.CASCADE)
#     product = models.ForeignKey(Product, on_delete=models.CASCADE)

#     class Meta:
#         unique_together = [['category', 'product']]

並且只需如下所示注冊“Product” ,您就可以使用默認中間表的內聯創建“Product”表的形式

“管理員.py”

from django.contrib import admin
from .models import Product

admin.site.register(Product)

這就是它的樣子。 如您所見, “類別”的 UI(用戶界面)與具有自定義中間表“CategoryProduct”時不同。 對我來說,擁有自定義中間表“CategoryProduct”時的 UI 更好:

在此處輸入圖像描述

即使您注冊“類別”表,如下所示。

“管理員.py”

from django.contrib import admin
from .models import Category

admin.site.register(Category)

默認中間表未內聯到“類別”表,如下所示:

在此處輸入圖像描述

要將默認中間表內聯到“類別”表“類別”表必須具有如下所示的ManyToManyField()

“模型.py”

from django.db import models

class Product(models.Model):
    name = models.CharField(max_length=255)

    def __str__(self):
        return self.name

class Category(models.Model):
    name = models.CharField(max_length=255)
    products = models.ManyToManyField( # Here
        Product, 
        # through='CategoryProduct'
    )

    def __str__(self):
        return self.name

# class CategoryProduct(models.Model):
#     category = models.ForeignKey(Category, on_delete=models.CASCADE)
#     product = models.ForeignKey(Product, on_delete=models.CASCADE)

#     class Meta:
#         unique_together = [['category', 'product']]

然后,只需如下所示注冊“Category” ,就可以使用默認中間表的內聯創建“Category”表的形式

“管理員.py”

from django.contrib import admin
from .models import Category

admin.site.register(Category)

這是它的樣子:

在此處輸入圖像描述

這就是您在Django中創建“多對多”關系的方式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM