问题
I have a Django form setup using GET method. Each value corresponds to attributes of a Django model. What would be the most elegant way to generate the query? Currently this is what I do in the view:
def search_items(request):
if 'search_name' in request.GET:
query_attributes = {}
query_attributes['color'] = request.GET.get('color', '')
if not query_attributes['color']: del query_attributes['color']
query_attributes['shape'] = request.GET.get('shape', '')
if not query_attributes['shape']: del query_attributes['shape']
items = Items.objects.filter(**query_attributes)
But I'm pretty sure there's a better way to go about it.
回答1:
You could do it with a list comp and and "interested params" set:
def search_items(request):
if 'search_name' in request.GET:
interested_params = ('color', 'shape')
query_attrs = dict([(param, val) for param, val in request.GET.iteritems()
if param in interested_params and val])
items = Items.objects.filter(**query_attrs)
Just for fun (aka don't actually do this) you could do it in one line:
def search_items(request):
items = Items.objects.filter(
**dict([(param, val) for param, val in request.GET.iteritems()
if param in ('color', 'shape') and val])
) if 'search_name' in request.GET else None
回答2:
well, the basic way you are approaching the problem seems sound, but the way you wrote it out looks a little funny. I'd probably do it this way:
def search_items(request):
if 'search_name' in request.GET:
query_attributes = {}
color = request.GET.get('color', '')
if color:
query_attributes['color'] = color
shape = request.GET.get('shape', '')
if shape:
query_attributes['shape'] = shape
items = Items.objects.filter(**query_attributes)
回答3:
If you want it to be fully dynamic, you can use a little bit of model introspection to find out what fields you can actually query, and filter only using those.
Though, this solution won't allow you to use __lookups in GET parameters, don't know if you need it.
def search_items(request):
if 'search_name' in request.GET:
all_fields = Items._meta.get_all_field_names()
filters = [(k, v) for k, v in request.GET.items() if k in all_fields]
items = Items.objects.filter(*filters)
回答4:
def search_items(request):
try:
items = Items.objects.filter(**dict([
(F, request.GET[F]) for F in ('color', 'shape')
]))
except KeyError:
raise Http404
Suppose 'color' and 'shape' are required GET params. Predefined tuple of filtering params is prefered because of security reasons.
来源:https://stackoverflow.com/questions/4011028/django-generating-a-queryset-from-a-get-request