2010-12-23 2 views
1

J'ai besoin d'aide pour trouver une manière efficace de faire une requête de recherche pour un ensemble d'objets, basé sur un Champ M2M. Mon formulaire de recherche va ressembler à Blue Cross Blue Shield | par exemple: this imageDjango: Comment faire une requête pour un objet basé sur un champ M2M (plusieurs sélections pour le champ sur le formulaire de recherche)

Maintenant, supposons que mon modèle ressemble à ceci:

# models.py 
class Provider(models.Model) 
    title = models.CharField(max_length=150) 
    phone = PhoneNumberField() 
    services_offered = models.ManyToManyField(ServiceType) 
     def __unicode__(self): 
      return self.title 

class ServiceCategory(models.Model): 
    service_category = models.CharField(max_length=30) 
    def __unicode__(self): 
    return self.service_category 
    class Meta(object): 
     verbose_name_plural = "Service Categories" 


class ServiceType(models.Model): 
    service_type = models.CharField(max_length=30) 
    service_category = models.ForeignKey(ServiceCategory)  
    def __unicode__(self): 
     return u'%s | %s' % (self.service_category, self.service_type 

De plus, nous devons garder à l'esprit que les options que nous choisissons sont sujets à changement, étant donné que leur affichage sur le formulaire est dynamique (de nouveaux ServiceCategories et ServiceTypes peuvent être ajoutés à tout moment). ? * Comment devrais-je aller à la construction d'une requête pour les objets du fournisseur, étant donné qu'une personne utilisant le formulaire de recherche sélectionner plusieurs Services_Offered *

Ceci est actuellement mon HAUTEMENT INEFFICACES MÉTHODE:

#managers.py 

    from health.providers.models import * 
    from django.db.models import Q 

    class Query: 
     def __init__(self): 
     self.provider_objects=Provider.objects.all() 
     self.provider_object=Provider.objects 
     self.service_object=ServiceType.objects 
     self.category_objects=ServiceCategory.objects.all() 

     def simple_search_Q(self, **kwargs): #matt's learning note: **kwargs passes any dictionary 
     return self.provider_objects.filter(
     Q(services_offered__service_type__icontains=kwargs['service']), 
     Q(title__icontains=kwargs['title']), 
     Q(state=kwargs['state']), 
     ).distinct().order_by('title') 

= ===================

#views.py 
    from django.shortcuts import render_to_response 
    from health.providers.models import * 
    from health.search.forms import * 
    from health.search.managers import Query #location of the query sets 
    from django.core.paginator import Paginator, InvalidPage, EmptyPage 
    from django.template import RequestContext 


    def simple_search(request): 
     if request.method == 'POST': 
     SimpleSearch_form = SimpleSearch(request.POST) 
     if SimpleSearch_form.is_valid(): 
      request.session["provider_list"] = None 
      kwargs = {'title': request.POST['title'], 
       'service': request.POST['service'], 'state': request.POST['state'] } 
      provider_list = Query().simple_search_Q(**kwargs) 
      return pagination_results(request, provider_list) 
     else: 
     SimpleSearch_form = SimpleSearch() 

     return render_to_response('../templates/index.html', { 'SimpleSearch_form': SimpleSearch_form}, 
      context_instance=RequestContext(request)) 

Comment puis-je faire ma requête:

  1. Obtenir des objets fournisseur basé sur la sélection de plusieurs request.POST [ 'service']

  2. plus efficace

Merci pour toute aide à l'avance.

Cordialement, Matt

+0

Comment définissez-vous votre formulaire de recherche? Utilisez-vous un 'ModelMultipleChoiceField' pour la liste des fournisseurs? –

+0

J'utilise les bibliothèques django-mptt pour générer mon formulaire dynamique. Voici un bon exemple qui explique comment l'utiliser http://django-mptt.github.com/django-mptt/forms.html#treenodechoicefield – Matt

Répondre

1

1: pour plusieurs request.POST [ 'service'], je suppose que vous voulez dire ce sont des cases à cocher.

Je créerais les ID de valeurs CheckBox, pas les noms, et effectuerais une recherche PK.

'services_offered__pk__in': request.POST.getlist('service') Cela renverrait tous les objets Provider qui ont TOUS les services sélectionnés. PS: Vous utilisez également CapitalCase pour les instances, ce qui est très déroutant. Si vous voulez que votre code soit lisible, je recommande fortement certaines modifications à votre style (n'utilisez pas CapitalCase pour les instances ou les variables) et rendez vos variables plus descriptives.

SimpleSearch_form = SimpleSearch() # what is SimpleSearch? 
simplesearch_form = SimpleSearchForm() # now, it's very clear what the class SimpleSearchForm is 
# and the form instance is clearly a for instance. 

2: le rendant plus efficace? Vous pouvez vous débarrasser de beaucoup de code et de séparation de code en supprimant toute votre classe Query. Aussi, je ne sais pas pourquoi vous utilisez des objets Q puisque vous ne faites rien qui le nécessiterait (comme OU ou OR + ET).

def simple_search(request): 
    if request.method == 'POST': 
     searchform = SimpleSearchForm(request.POST) 

     if searchform.is_valid(): 
      request.session['provider_list'] = None 
      post = request.POST 
      providers = Provider.objects.filter(services_offered__pk__in=post.getlist('services'), 
       title=post['title'], state=post['state']) 
      return pagination_results(request, provider_list) 
    else: 
     searchform = SimpleSearchForm() 

    return direct_to_template(request, '../templates/index.html', { 'searchform': searchform}) 
+0

Yuji! Je t'aime. Merci beaucoup. J'ai programmé en Python par le passé, mais c'est mon premier projet Django (c'est un travail humanitaire non rémunéré).Donc, j'aurais probablement fait quelque chose de très inefficace. J'apprécie votre approche rapide et concise pour m'aider à résoudre mon problème. – Matt

+0

Hey pas de problème! C'est aussi du travail non rémunéré: D C'est amusant. –

+0

Eh bien, je vais certainement vous donner du crédit pour l'aide, si vous souhaitez ajouter quelque chose à votre CV. Je prévois de déployer le site Web pour le comté de Charlotte-Meck en janvier. Juste savoir lemme. Encore une fois merci. :) – Matt

Questions connexes