2016-08-17 8 views
1

Django 1.8.4 add GenericForeignKey検索フィールドが機能しません。Django add GenericForeignKey検索フィールド

私のようないくつかの製品モデルを作成しました:

class Product1(models.Model): 
    ... 
    orders = GenericRelation(Order) 

class Product2(models.Model): 
    ... 
    orders = GenericRelation(Order) 

と注文モデルに:、

class Order(models.Model): 
    content_type = models.ForeignKey(
     ContentType, 
     blank=True, 
     null=True 
     ) 
    object_id = models.PositiveIntegerField(
     blank=True, 
     null=True 
     ) 
    product = generic.GenericForeignKey('content_type','object_id') 

このすべてが正常に動作します

をしかし、私は中Produt名を検索するときOrderAdmin、次のようなprodct__name検索フィールドを追加しました:

class OrderAdmin(admin.ModelAdmin): 
    ... 
    search_fields = [ 
     'product__name', 
    ] 

これは機能しません!

Djangoはそれを上げる:

Field 'product' does not generate an automatic reverse relation and therefore cannot be used for reverse querying. 
If it is a GenericForeignKey, consider adding a GenericRelation. 

は、Djangoの1.8 GenericForeignKeyがどのように機能するかを理解しないでください、GenericRelationsはすでに製品モデルに存在しますが、まだ動作しません。

答えて

1

デフォルトのget_search_resultsメソッドをオーバーライドすると、次のコードは一般的には動作しますが、少し問題があります。

def get_search_results(self, request, queryset, search_term): 
    """Override to Include searching `product__name` which is a 
    GenericForeignKey Field of all product types. 
    Returns a tuple containing a queryset to implement the search, 
    and a boolean indicating if the results may contain duplicates. 
    """ 
    products = [v for k, v in pro_models.PRODUCT_DICT.iteritems()] 
    generic_queryset = queryset 

    product_list = list() 
    for bit in search_term.split(): 
     for product in products: 
      product_queryset = product.objects.filter(
       Q(name__icontains=bit)) 
      product_list += list(product_queryset) 

     generic_query = [Q(**{ 
      'content_type': ContentType.objects.get_for_model(product), 
      'object_id': product.id 
     }) for product in product_list] 

     if generic_query: 
      generic_queryset = generic_queryset.filter(
       reduce(operator.or_, generic_query)) 
     else: 
      generic_queryset = generic_queryset.none() 

    default_queryset, use_distinct = \ 
     super(OrderAdmin, self).get_search_results(
      request, 
      queryset, 
      search_term 
     ) 
    return default_queryset | generic_queryset, use_distinct 
関連する問題