提问者:小点点

用AJAX和Django Rest框架动态过滤queryset


from django.db import models
from django.utils import timezone
import datetime
from django.core.validators import RegexValidator, MinLengthValidator
from .validator import validate_gearshift

class Coche(models.Model):
    matricula = models.CharField(max_length=7,primary_key=True,validators=[RegexValidator(regex='^[1-9]{4}[A-Z]{3}$',message="La matr>    concesionario = models.ForeignKey('Concesionario', on_delete=models.CASCADE)
    brand = models.ForeignKey('CocheBrand', on_delete=models.CASCADE)
    model_name= models.ForeignKey('CocheModel', on_delete=models.CASCADE)
    type_car = models.ForeignKey('CocheType', on_delete=models.CASCADE)
    location = models.ForeignKey('Localidad', on_delete=models.CASCADE)
    warranty = models.ForeignKey('CocheWarranty', on_delete=models.CASCADE)
    doors = models.ForeignKey('CocheDoors', on_delete=models.CASCADE)
    gearshift = models.ForeignKey('CocheGearshift', on_delete=models.CASCADE)
    precio = models.DecimalField(verbose_name="Precio",max_digits=10, decimal_places=5, validators=[RegexValidator(regex='^[1-9][0-9]>    rebaja = models.DecimalField(verbose_name="Rebaja",max_digits=10, decimal_places=5, validators=[RegexValidator(regex='^[0-9]$|^[1>    precio_final = models.DecimalField(verbose_name="Precio Final",max_digits=10, decimal_places=5, null=True, blank=True) #se calcul>    kilometres = models.IntegerField(verbose_name="Kilometros", validators=[RegexValidator(regex='^[0-9]$|^[0-9][0-9]$|^[0-9][0-9][0->    years = models.IntegerField(verbose_name="Años", validators=[RegexValidator(regex='^[0-9]$|^[12][0-9]$|^(30)$',message="La antigu>    horsepower = models.IntegerField(verbose_name="Caballos", validators=[RegexValidator(regex='^[6789][0-9]$|^[12][0-9][0-9]$|^(300)>    description = models.CharField(verbose_name="Descripcion", max_length=512)
    reserved = models.BooleanField(verbose_name="Reservado")
    sold = models.BooleanField(verbose_name="Vendido")
    create_at = models.DateTimeField(auto_now_add=True,verbose_name="Fecha Creacion")
    def __str__(self):
        return self.matricula
    def FormatoFecha(self):
        return self.fecha.strftime('%d - %b -%y')
from .models import Coche, CocheGearshift, CocheDoors, CocheWarranty, Localidad, CocheType, CocheModel, CocheBrand, Concesionario, Co>from django.views.generic import ListView
from django.shortcuts import render
from .forms import IndexSearch

from django.http import JsonResponse
from rest_framework.generics import ListAPIView
from .serializers import CocheSerializers
from .pagination import StandardResultsSetPagination

def CocheList(request):
    return render(request,'wallacar_app/prueba.html', {})

class CochesListing(ListAPIView):
    pagination_class = StandardResultsSetPagination
    serializer_class = CocheSerializers
    def get_queryset(self):
        queryList = Coche.objects.all()
        brand = self.request.query_params.get('brand',None)
        model_name = self.request.query_params.get('model_name',None)
        type_car = self.request.query_params.get('type_car',None)
        location = self.request.query_params.get('location',None)
        doors = self.request.query_params.get('doors',None)
        gearshift = self.request.query_params.get('gearshift',None)
        sort_by = self.request.query_params.get('sort_by',None)
        horsepower = self.request.query_params.get('horsepower',None)

        if brand:
            queryList = queryList.filter(brand = brand)
        if model_name:
            queryList = queryList.filter(model_name = model_name)
        if type_car:
            queryList = queryList.filter(type_car = type_car)
        if location:
            queryList = queryList.filter(location = location)
        if doors:
            queryList = queryList.filter(doors = doors)
        if gearshift:
            queryList = queryList.filter(gearshift = gearshift)
        if horsepower:
            queryList = queryList.filter(horsepower = horsepower)


        if sort_by == 'precio_final':
            quereyList = queryList.order_by('precio_final')
        elif sort_by == 'years':
            queryList = queryList.order_by('years')
        return queryList



def getBrand(request):
    if request.method == "GET" and request.is_ajax():
        brand = Coche.objects.exclude(brand__isnull=True).exclude(brand__exact='').order_by('brand').values_list('brand').distinct()
        brand = [i[0] for i in list(brand)]
        data = {'brand':brand,}
        return JsonResponse(data, status = 200)

def getModel(request):
    if request.method == "GET" and request.is_ajax():
        model_name = Coche.objects.exclude(model_name__isnull=True).exclude(model_name__exact='').order_by('model_name').values_list(>        model_name = [i[0] for i in list(model_name)]
        data = {'model_name',model_name}
        return JsonResponse(data,status=200)

def getType(request):
    if request.method == "GET" and request.is_ajax():
        type_car = Coche.objects.exclude(type_car__isnull=True).exclude(type_car__exact='').order_by('type_car').values_list('type_ca>        type_car = [i[0] for i in list(type_car)]
        data = {'type_car',type_car}
        return JsonResponse(data,status=200)

def getLocation(request):
    if request.method == "GET" and request.is_ajax():
        location = Coche.objects.exclude(location__isnull=True).exclude(location__exact='').order_by('location').values_list('locatio>        location = [i[0] for i in list(location)]
        data = {'location',location}
        return JsonResponse(data,status=200)

def getDoors(request):
    if request.method == "GET" and request.is_ajax():
        doors = Coche.objects.exclude(doors__isnull=True).exclude(doors__exact='').order_by('doors').values_list('doors').distinct()
        doors = [i[0] for i in list(doors)]
        data = {'doors',doors}
        return JsonResponse(data,status=200)

def getGearshift(request):
    if request.method == "GET" and request.is_ajax():
        gearshift = Coche.objects.exclude(gearshift__isnull=True).exclude(gearshift__exact='').order_by('gearshift').values_list('gea>        gearshift = [i[0] for i in list(gearshift)]
        data = {'gearshift',gearshift}
        return JsonResponse(data,status=200)

def getHorsepower(request):
    if request.method == "GET" and request.is_ajax():
        horsepower = Coche.objects.exclude(horsepower__isnull=True).exclude(horsepower__exact='').order_by('horsepower').values_list(>        horsepower = [i[0] for i in list(horsepower)]
        data = {'horsepower',horsepower}
        return JsonResponse(data,status=200)

from rest_framework import serializers
from .models import Coche

class CocheSerializers(serializers.ModelSerializer):
    class Meta:
        model = Coche
        fields = ('brand','model_name','type_car','location','doors','gearshift','years','precio_final'.'horsepower','kilometres')
from django.urls import path
from wallacar_app.views import *

urlpatterns = [
    path('lista/', CocheList),
    path("listado_coches/", CocheListing.as_view(), name = 'listing'),
    path("ajax/marca/", getBrand, name = 'get_brand'),
    path("ajax/model/", getModel, name = 'get_model'),
    path("ajax/location/", getLocation, name = 'get_location'),
    path("ajax/type/", getType, name = 'get_type'),
    path("ajax/doors/", getDoors, name = 'get_doors'),
    path("ajax/gearshift/", getGearshift, name = 'get_gearshift'),
    path("ajax/horsepower/", getHorsepower, name = 'get_horsepower'),
]
from django.contrib import admin
from django.urls import path
from django.conf.urls import url, include

from django.conf import settings
from django.conf.urls.static import static


urlpatterns = [
    path('admin/', admin.site.urls),
    path(r'^wallacar_app/',include(("wallacar_app.urls","wallacar_app"), namespace = "wallacar_app"))
]
var send_data = {}

$(document).ready(function () {


    resetFilters();


    getAPIData();



    getModel();
    getType();
    getLocation();
    getDoors();
    getGearshift();
    getHorsepower();




    $('#model_name').on('change', function () {
  

        $("#brand").val("all");
        send_data['brand'] = '';


        if(this.value == "all")
            send_data['model_name'] = "";
        else
            send_data['model_name'] = this.value;



        getBrand(this.value);


        getAPIData();
    });



    $('#type_car').on('change', function () {
        // get the api data of updated variety

        if(this.value == "all")
            send_data['type_car'] = "";
        else
            send_data['type_car'] = this.value;
        getAPIData();
    });




    $('#location').on('change', function () {

        if(this.value == "all")
            send_data['location'] = "";
        else
            send_data['location'] = this.value;
        getAPIData();
    });


    $('#doors').on('change', function () {
        // get the api data of updated variety

        if(this.value == "all")
            send_data['doors'] = "";
        else
            send_data['doors'] = this.value;
        getAPIData();
    });





    $('#gearshift').on('change', function () {
        // get the api data of updated variety

        if(this.value == "all")
            send_data['gearshift'] = "";
        else
            send_data['gearshift'] = this.value;
        getAPIData();
    });



    $('#horsepower').on('change', function () {
        // get the api data of updated variety

        if(this.value == "all")
            send_data['horsepower'] = "";
        else
            send_data['horsepower'] = this.value;
        getAPIData();
    });


    $('#brand').on('change', function () {
        if(this.value == "all")
            send_data['brand'] = "";
        else
            send_data['brand'] = this.value;
        getAPIData();
    });

    $('#sort_by').on('change', function () {
        send_data['sort_by'] = this.value;
        getAPIData();
    });



    $("#display_all").click(function(){
        resetFilters();
        getAPIData();
    })
})

function resetFilters() {
    $("#brand").val("all");
    $("#model_name").val("all");
    $("#type_car").val("all");
    $("#doors").val("all");
    $("#gearshift").val("all");
    $("#horsepower").val("all");
    $("#sort_by").val("none");



    getBrand("all");
    getType("all");
    getLocation("all");
    getDoors("all");
    getGearshift("all");
    getHorsepower("all");
    getModel("all");

    send_data['brand'] = '';
    send_data['model_name'] = '';
    send_data['type_car'] = '';
    send_data['doors'] = '';
    send_data['horsepower'] = '';
    send_data['gearshift'] = '';
    send_data["sort_by"] = '',
    send_data['format'] = 'json';
}

function putTableData(result) {


    let row;
    if(result["results"].length > 0){
        $("#no_results").hide();
        $("#list_data").show();
        $("#listing").html("");
        $.each(result["results"], function (a, b) {
            row = "<tr> <td>" + b.brand + "</td>" +
            "<td>" + b.model_name + "</td>" +
            "<td>" + b.type_car + "</td>" +
                "<td>" + b.doors + "</td>" +
                "<td>" + b.location + "</td>" +
                "<td>" + b.gearshift + "</td>" +
                "<td>" + b.horsepower + "</td>" +
            $("#listing").append(row);
        });
    }
    else{


        $("#no_results h5").html("No results found");
        $("#list_data").hide();
        $("#no_results").show();
    }

    let prev_url = result["previous"];
    let next_url = result["next"];


    if (prev_url === null) {
        $("#previous").addClass("disabled");
        $("#previous").prop('disabled', true);
    } else {
        $("#previous").removeClass("disabled");
        $("#previous").prop('disabled', false);
    }
    if (next_url === null) {
        $("#next").addClass("disabled");
        $("#next").prop('disabled', true);
    } else {
        $("#next").removeClass("disabled");
        $("#next").prop('disabled', false);
    }

    $("#previous").attr("url", result["previous"]);
    $("#next").attr("url", result["next"]);

    $("#result-count span").html(result["count"]);
}

function getAPIData() {
    let url = $('#list_data').attr("url")
    $.ajax({
        method: 'GET',
        url: url,
        data: send_data,
        beforeSend: function(){
            $("#no_results h5").html("Cargando...");
        },
        success: function (result) {
            putTableData(result);
        },
        error: function (response) {
            $("#no_results h5").html("Algo no funciona....");
            $("#list_data").hide();
        }
    });
}

$("#next").click(function () {

    let url = $(this).attr("url");
    if (!url)
        $(this).prop('all', true);

    $(this).prop('all', false);
    $.ajax({
        method: 'GET',
        url: url,
        success: function (result) {
            putTableData(result);
        },
        error: function(response){
            console.log(response)
        }
    });
})

$("#previous").click(function () {

    let url = $(this).attr("url");
    if (!url)
        $(this).prop('all', true);

    $(this).prop('all', false);
    $.ajax({
        method: 'GET',
        url: url,
        success: function (result) {
            putTableData(result);
        },
        error: function(response){
            console.log(response)
        }
    });
})

function getBrand(model_name) {


    let url = $("#brand").attr("url");

    let brand_option = "<option value='all' selected>TODAS LAS MARCAS</option>";

    $.ajax({
        method: 'GET',
        url: url,
        data: {"model_name":model_name},
        success: function (result) {
            $.each(result["brand"], function (a, b) {
                brand_option += "<option>" + b + "</option>"
            });
            $("#brand").html(brand_option)
        },
        error: function(response){
            console.log(response)
        }
    });
}

function getModel() {


    let url = $("#model_name").attr("url");


    $.ajax({
        method: 'GET',
        url: url,
        data: {},
        success: function (result) {
            model_options = "<option value='all' selected>TODOS LOS MODELOS</option>";
            $.each(result["model_name"], function (a, b) {
                model_options += "<option>" + b + "</option>"
            });
            $("#model_name").html(model_options)
        },
        error: function(response){
            console.log(response)
        }
    });
}

function getType() {


    let url = $("#type_car").attr("url");


    $.ajax({
        method: 'GET',
        url: url,
        data: {},
        success: function (result) {
            type_options = "<option value='all' selected>TODOS LOS TIPOS</option>";
            $.each(result["type_car"], function (a, b) {
                type_option += "<option>" + b + "</option>"
            });
            $("#type_car").html(type_option)
        },
        error: function(response){
            console.log(response)
        }
    });
}

function getDoors() {


    let url = $("#doors").attr("url");


    $.ajax({
        method: 'GET',
        url: url,
        data: {},
        success: function (result) {
            doors_options = "<option value='all' selected>TODAS LAS PUERTAS</option>";
            $.each(result["doors"], function (a, b) {
                doors_options += "<option>" + b + "</option>"
            });
            $("#doors").html(doors_options)
        },
        error: function(response){
            console.log(response)
        }
    });
}



function getLocation() {


    let url = $("#location").attr("url");


    $.ajax({
        method: 'GET',
        url: url,
        data: {},
        success: function (result) {
            location_options = "<option value='all' selected>TODAS LAS LOCALIZACIONES</option>";
            $.each(result["location"], function (a, b) {
                location_options += "<option>" + b + "</option>"
            });
            $("#location").html(location_options)
        },
        error: function(response){
            console.log(response)
        }
    });
}



function getGearshift() {


    let url = $("#gearshift").attr("url");


    $.ajax({
        method: 'GET',
        url: url,
        data: {},
        success: function (result) {
            gearshift_options = "<option value='all' selected>TODAS LAS MARCHAS</option>";
            $.each(result["gearshift"], function (a, b) {
                gearshift_options += "<option>" + b + "</option>"
            });
            $("#gearshift").html(gearshift_options)
        },
        error: function(response){
            console.log(response)
        }
    });
}


function getHorsepower() {


    let url = $("#horsepower").attr("url");


    $.ajax({
        method: 'GET',
        url: url,
        data: {},
        success: function (result) {
            horsepower_options = "<option value='all' selected>TODOS LOS CABALLOS</option>";
            $.each(result["horsepower"], function (a, b) {
                horsepower_options += "<option>" + b + "</option>"
            });
            $("#horsepower").html(horsepower_options)
        },
        error: function(response){
            console.log(response)
        }
    });
}
{% extends "base.html" %}
{% load static %}
{% block style %}
    <style type="text/css">
    .properties_table{
       min-height: 540px;
       font-size: 14px;
    }
    </style>
{% endblock %}
{% block content %}
    <section class="site_filter">
        <div class="container-fluid">
            <div class="row">
                <div class="col-sm-2 col-2">
                    <div class="form-group">
                        <label for="brand">MARCAS</label>
                        <select class="form-control" id="brand"
                            url = "{%url 'wallacar_app:get_brand' %}">
                        </select>
                    </div>
                </div>
                <div class="col-sm-2 col-2">
                    <div class="form-group">
                        <label for="model_name">MODELOS</label>
                        <select class="form-control" id="model_name"
                            url = "{%url 'wallacar_app:get_model' %}">
                        </select>
                    </div>
                </div>
                <div class="col-sm-2 col-2">
                    <div class="form-group">
                        <label for="type_car">TIPO DE COCHE</label>
                        <select class="form-control" id="type_car"
                            url = "{%url 'wallacar_app:get_type' %}">
                            <option value='all' selected>TODOS LOS TIPOS</option>
                        </select>
                    </div>
                </div>
                <div class="col-sm-2 col-2">
                    <div class="form-group">
                        <label for="location">LOCALIZACIÓN</label>
                        <select class="form-control" id="location" url = "{%url 'wallacar_app:get_location' %}">
                            <option value='all' selected>TODAS LAS LOCALIZACIONES</option>
                        </select>
                    </div>
                </div>
                <div class="col-sm-2 col-2">
                    <div class="form-group">
                        <label for="doors">PUERTAS</label>
                        <select class="form-control" id="doors" url = "{%url 'wallacar_app:get_doors' %}">
                            <option value='all' selected>TODAS LAS PUERTAS</option>
                        </select>
                    </div>
                </div>
                <div class="col-sm-2 col-2">
                    <div class="form-group">
                        <label for="gearshift">CAMBIOS</label>
                        <select class="form-control" id="gearshift" url = "{%url 'wallacar_app:get_gearshift' %}">
                            <option value='all' selected>TODOS LOS CAMBIOS</option>
                        </select>
                    </div>
                </div>
                <div class="col-sm-2 col-2">
                    <div class="form-group">
                        <label for="horsepower">CAMBIOS</label>
                        <select class="form-control" id="horsepower" url = "{%url 'wallacar_app:get_horsepower' %}">
                            <option value='all' selected>TODOS LOS CABALLOS</option>
                        </select>
                    </div>
                </div>
                <div class="col-sm-2 col-2">
                    <div class="form-group">
                        <label for="sort_by">ORDENAR POR </label>
                        <select class="form-control" id="sort_by">
                            <option selected="true"
                            disabled="disabled" value = "none">Elige una opcion</option>
                            <option value='precio_final'>PRECIO</option>
                            <option value='years'>AÑOS</option>
                        </select>
                    </div>
                </div>
                <div class="col-sm-2 col-2">
                    <div class="row justify-content-center align-self-center"
                        style="color:white; margin-top:30px;">
                        <a class="btn btn-secondary" id="display_all">Mostrar todos</a>
                    </div>
                </div>
            </div>
        </div>
    </section>
    <br />
    <section>
        <div class="container-fluid">
            <div id = "result-count" class="text-right">
                <span class='font-weight-bold'></span> resultados encontrados.
            </div>
            <div class="row properties_table justify-content-center">
                <div id = "no_results">
                    <h5>no hay resultados</h5>
                </div>
                <table class="table table-bordered table-responsive table-hover table-striped"
                 id="list_data" data-toggle="table" url = "{% url 'wallacar_app:listing' %}">
                    <thead>
                        <tr>
                            <th data-field="brand">MARCA</th>
                            <th data-field="model_name">MODELO</th>
                            <th data-field="type_car">TIPO</th>
                            <th data-field="location">LOCALIZACIÓN</th>
                            <th data-field="doors">PUERTAS</th>
                            <th data-field="gearshift">CAMBIOS</th>
                            <th data-field="horsepower">CABALLOS</th>
                        </tr>
                    </thead>
                    <tbody id="listing">
                    </tbody>
                </table>
            </div>
            <div class="row justify-content-center">
                <nav aria-label="navigation">
                    <ul class="pagination">
                        <li class="page-item">
                            <button class="btn btn-primary page-link" id="previous">Previous</button>
                        </li>
                        <li class="page-item pull-right">
                            <button class="btn btn-primary page-link" id="next">Next</button>
                        </li>
                    </ul>
                </nav>
            </div>
        </div>
    </section>
{% endblock %}
{% block script %}
    <script src="{% static 'js/wallacar.js' %}" type="text/javascript">
    </script>
{% endblock %}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
{% block head %}
{% endblock %}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
{% block style %}
{% endblock %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
</head>
<body>
{% block content %}
{% endblock %}
{% block script %}
{% endblock %}
</body>
</html>
File "./wallacar_app/views.py", line 9, in <module>
    from .serializers import CocheSerializers

Exception Type: SyntaxError at /
Exception Value: invalid syntax (serializers.py, line 7)

我正在使用Django3.1.7和指南:指南我正在尝试做下拉式dinamic查询,我不知道是否有一个更好的形式来做这件事...没有必要使用Django Rest框架,我可以自由使用我想要的所有东西。


共1个答案

匿名用户

您看过DRF文档中针对查询参数和Django过滤器后端的过滤吗?首先,您不需要sort_by参数,因为DRF内置了OrderingFilter。

我建议使用django-rest-framework-filters。是的,您必须阅读大量文档并理解内部内容,但滚动您自己的解析查询参数实现(在这里您基本上传递用户输入而不敏感地构建queryset)是一个非常大的安全危险信号。更不用说,它也很容易出错,并且不遵循django所依据的Don't Repeat Yourself(DRY)原则。