Django 2.1.7: заполнение дочернего поля с выбранными родительскими атрибутами в модели продукта - PullRequest
2 голосов
/ 30 апреля 2019

у меня есть 3 модели: Category, SubCategory и Product.

SubCategory относится к Category с Foreignkey, а Product относится к Category и Subcategory через ForeignKey.

What My Db looks like:

Category: Kids
    -->SubCategory: Beanies
Category: Men
    -->SubCategory: Hoodies

Теперь, когда я хочу добавить продукт и выбираю Kids, на странице администрирования Product я хочу, чтобы отображались только связанные подкатегории.

Что я пробовал:

  1. используя formfield_for_foreignkey, но я не могу понять, как это работает.

  2. Я сталкивался с этим вопросом Администратор Django Показать / скрыть поля, если в раскрывающемся списке выбрано конкретное значение , но я думаю, что это больше связано с полем, чем со значением.

Предложения, которые я нашел онлайн:

  • используйте ajax для извлечения подкатегорий и вставьте их в дочернее поле.

Мои модели:

class Category(models.Model):
    name = models.CharField(max_length=250, db_index=True, unique=True)
    slug = models.SlugField(max_length=250, db_index=True, unique=True)

class SubCategory(models.Model):
    parent = models.ForeignKey(Category, on_delete=models.CASCADE)
    name = models.CharField(max_length=250, db_index=True)
    slug = models.SlugField(max_length=250, db_index=True)

class Product(models.Model):  
    parent = models.ForeignKey(Category, on_delete=models.CASCADE, related_name="category")
    child = models.ForeignKey(SubCategory, on_delete=models.CASCADE)
    name = models.CharField(max_length=250, unique=True, db_index=True)
    slug = models.SlugField(max_length=250, unique=True, db_index=True)

Мои модели администратора:

@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
    list_display = [
        'name', 'slug'
    ]

@admin.register(SubCategory)
class SubCategoryAdmin(admin.ModelAdmin):
    prepopulated_fields = {'slug':('name',)}
    list_display = [
        'name', 'slug', 'parent',
    ]
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    list_display = [
        'name', 'slug', 'child', 
    ]
    prepopulated_fields = {'slug':('name',)}
    list_per_page = 20

    class Media:
        js = ('javascript/hide_child_if_parent_is_none.js', )

1 Ответ

0 голосов
/ 03 мая 2019

Я исправил это с помощью Django Rest Framework & AJAX, это был интересный опыт.Вот код

в SubCategory Модель. Я отредактировал свое поле parent, добавив к нему related_name и удалив его из Product.parent

parent = models.ForeignKey(Category, on_delete=models.CASCADE, related_name="children")

Мои сериализаторы:

from rest_framework import serializers
from catalogue.models import Category, SubCategory
from drf_writable_nested import WritableNestedModelSerializer
# Create your serializers here.

class SubCategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = SubCategory
        fields = ('id', 'name',)

class CategorySerializer(WritableNestedModelSerializer):
    children = SubCategorySerializer(many=True)
    class Meta:
        model = Category
        fields = ('id', 'name', 'children')

мой AJAX звонок:

(function($) {
    $(function() {
        var selectField = $('#id_parent'),verified = $('#id_child');

        function toggleVerified(value) {
            if (value) {
                verified.show();
                console.log(value);
            } else {
                verified.hide();
            };
        };

        function getCookie(name) {
            var cookieValue = null;
            if (document.cookie && document.cookie !== '') {
                var cookies = document.cookie.split(';');
                for (var i = 0; i < cookies.length; i++) {
                    var cookie = cookies[i].trim();
                    if (cookie.substring(0, name.length + 1) === (name + '=')) {
                        cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                        break;
                    }
                }
            }
            return cookieValue;
        };
        var csrftoken = getCookie('csrftoken');

        function plugOptions(array, target){
            var children = array.children;
            //console.log(children);
            target.empty();
            target.append(new Option("---------", false))
            $.each(children, function(key){
                target.append(new Option(children[key].name, children[key].id));
            });
        };

        // show/hide on load based on pervious value of selectField
        toggleVerified(selectField.val());

        // show/hide on change
        selectField.change(function() {
            toggleVerified($(this).val());

            $.ajaxSetup({
                beforeSend: function(xhr, settings) {
                    xhr.setRequestHeader("X-CSRFToken", csrftoken);
                }
            });
            $.ajax({
                type: 'GET',
                url: '/my_api/categories/'+$(this).val(),
                contentType: "application/json; charset=utf-8",
                success: function(resp) {
                    console.log("success"),
                    plugOptions(resp, verified)
                },
                error: function(jqXHR, textStatus, errorThrown) {
                    console.log(jqXHR),
                    console.log(textStatus),
                    console.log(errorThrown)
               }
            });
        });
    });
})(django.jQuery);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...