endpoint, frontend
This commit is contained in:
parent
6a35148188
commit
8e29a715a5
@ -50,6 +50,7 @@ INSTALLED_APPS = [
|
||||
"corsheaders",
|
||||
"django_filters",
|
||||
# apps
|
||||
'cars'
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
@ -154,7 +155,4 @@ DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
||||
|
||||
|
||||
# CORS
|
||||
CORS_ALLOWED_ORIGINS = env(
|
||||
"ALLOWED_ORIGINS",
|
||||
default="http://localhost:3000",
|
||||
).split()
|
||||
CORS_ALLOW_ALL_ORIGINS = True
|
||||
|
27
backend/cars/migrations/0001_initial.py
Normal file
27
backend/cars/migrations/0001_initial.py
Normal file
@ -0,0 +1,27 @@
|
||||
# Generated by Django 3.2.9 on 2022-01-15 15:58
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Car',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('mark', models.CharField(max_length=150)),
|
||||
('model', models.CharField(max_length=150)),
|
||||
('mileage', models.PositiveIntegerField()),
|
||||
('production_year', models.PositiveSmallIntegerField()),
|
||||
('engine_capacity', models.DecimalField(decimal_places=2, max_digits=16)),
|
||||
('combustion', models.DecimalField(decimal_places=2, max_digits=16)),
|
||||
('price', models.DecimalField(decimal_places=2, max_digits=16)),
|
||||
],
|
||||
),
|
||||
]
|
@ -5,9 +5,9 @@ class Car(models.Model):
|
||||
model = models.CharField(max_length=150)
|
||||
mileage = models.PositiveIntegerField()
|
||||
production_year = models.PositiveSmallIntegerField()
|
||||
engine_capacity = models.DecimalField()
|
||||
combustion = models.DecimalField()
|
||||
price = models.DecimalField()
|
||||
engine_capacity = models.DecimalField(decimal_places=2, max_digits=16)
|
||||
combustion = models.DecimalField(decimal_places=2, max_digits=16)
|
||||
price = models.DecimalField(decimal_places=2, max_digits=16)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return "Car"
|
@ -1,12 +1,7 @@
|
||||
from django.urls import path, include
|
||||
from rest_framework.routers import DefaultRouter
|
||||
from .views import CarViews
|
||||
|
||||
# Create a router and register our viewsets with it.
|
||||
router = DefaultRouter()
|
||||
router.register(r'cars', CarViews.as_view(), name="cars")
|
||||
from .views import CarList
|
||||
|
||||
# The API URLs are now determined automatically by the router.
|
||||
urlpatterns = [
|
||||
path('', include(router.urls)),
|
||||
path('cars', CarList.as_view()),
|
||||
]
|
25
backend/cars/utils.py
Normal file
25
backend/cars/utils.py
Normal file
@ -0,0 +1,25 @@
|
||||
VALUES = ['low', 'mid', 'high']
|
||||
|
||||
|
||||
def production_year_to_value(production_year):
|
||||
return VALUES[["Dawno", "Średnio", "Niedawno"].index(production_year)]
|
||||
|
||||
def mileage_to_value(mileage):
|
||||
return VALUES[["Niski", "Średni", "Duży"].index(mileage)]
|
||||
|
||||
def engine_capacity_to_value(engine_capacity):
|
||||
return VALUES[["Mała", "Średnia", "Ogromna"].index(engine_capacity)]
|
||||
|
||||
def combustion_to_value(combustion):
|
||||
return VALUES[["Niskie", "Średnie", "Wysokie"].index(combustion)]
|
||||
|
||||
|
||||
def map_query_params(query_params):
|
||||
values = {}
|
||||
params = ['production_year', 'mileage', 'engine_capacity', 'combustion']
|
||||
funcs = [production_year_to_value, mileage_to_value, engine_capacity_to_value, combustion_to_value]
|
||||
for param, func in zip(params, funcs):
|
||||
if (query_param := query_params.get(param)):
|
||||
values[param] = func(query_param)
|
||||
return values
|
||||
|
@ -1,19 +1,15 @@
|
||||
from rest_framework.views import APIView
|
||||
from .models import Car
|
||||
from rest_framework import generics
|
||||
from rest_framework.response import Response
|
||||
|
||||
|
||||
class CarViews(APIView):
|
||||
def get(self, request, format=None):
|
||||
"""
|
||||
Returns car list based on fuzzy_logic filters.
|
||||
"""
|
||||
combustion = request.query_params.get('combustion')
|
||||
mileage = request.query_params.get('mileage')
|
||||
production_year = request.query_params.get('production_year')
|
||||
engine_capacity = request.query_params.get('engine_capacity')
|
||||
|
||||
print(combustion, mileage, production_year, engine_capacity)
|
||||
|
||||
cars = list(Car.objects.all())
|
||||
return Response(cars)
|
||||
from .models import Car
|
||||
from .serializers import CarSerializer
|
||||
from .utils import map_query_params
|
||||
class CarList(generics.ListAPIView):
|
||||
queryset = Car.objects.all()
|
||||
serializer_class = CarSerializer
|
||||
|
||||
|
||||
def list(self, request):
|
||||
values = map_query_params(request.query_params)
|
||||
queryset = self.get_queryset()
|
||||
serializer = CarSerializer(queryset, many=True)
|
||||
return Response(serializer.data)
|
1
dev.env
1
dev.env
@ -1,3 +1,4 @@
|
||||
SECRET_KEY=SECRET_KEY
|
||||
DEBUG=1
|
||||
ALLOWED_HOSTS=localhost 127.0.0.1
|
||||
ALLOWED_ORIGINS=http://localhost:8080 http://127.0.01:8080
|
32
frontend/package-lock.json
generated
32
frontend/package-lock.json
generated
@ -7,6 +7,7 @@
|
||||
"": {
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"axios": "^0.24.0",
|
||||
"core-js": "^3.6.5",
|
||||
"vue": "^2.6.11",
|
||||
"vue-router": "^3.2.0",
|
||||
@ -2610,7 +2611,6 @@
|
||||
"thread-loader": "^2.1.3",
|
||||
"url-loader": "^2.2.0",
|
||||
"vue-loader": "^15.9.2",
|
||||
"vue-loader-v16": "npm:vue-loader@^16.1.0",
|
||||
"vue-style-loader": "^4.1.2",
|
||||
"webpack": "^4.0.0",
|
||||
"webpack-bundle-analyzer": "^3.8.0",
|
||||
@ -3394,6 +3394,14 @@
|
||||
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "0.24.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz",
|
||||
"integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.14.4"
|
||||
}
|
||||
},
|
||||
"node_modules/babel-code-frame": {
|
||||
"version": "6.26.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
|
||||
@ -3711,7 +3719,6 @@
|
||||
"@types/node": "*",
|
||||
"anymatch": "^3.0.3",
|
||||
"fb-watchman": "^2.0.0",
|
||||
"fsevents": "^2.3.2",
|
||||
"graceful-fs": "^4.2.4",
|
||||
"jest-regex-util": "^27.0.6",
|
||||
"jest-serializer": "^27.0.6",
|
||||
@ -4862,7 +4869,6 @@
|
||||
"dependencies": {
|
||||
"anymatch": "~3.1.2",
|
||||
"braces": "~3.0.2",
|
||||
"fsevents": "~2.3.2",
|
||||
"glob-parent": "~5.1.2",
|
||||
"is-binary-path": "~2.1.0",
|
||||
"is-glob": "~4.0.1",
|
||||
@ -7207,8 +7213,7 @@
|
||||
"esprima": "^4.0.1",
|
||||
"estraverse": "^4.2.0",
|
||||
"esutils": "^2.0.2",
|
||||
"optionator": "^0.8.1",
|
||||
"source-map": "~0.6.1"
|
||||
"optionator": "^0.8.1"
|
||||
},
|
||||
"bin": {
|
||||
"escodegen": "bin/escodegen.js",
|
||||
@ -8224,7 +8229,6 @@
|
||||
"version": "1.14.5",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.5.tgz",
|
||||
"integrity": "sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
}
|
||||
@ -10509,7 +10513,6 @@
|
||||
"@jest/types": "^24.9.0",
|
||||
"anymatch": "^2.0.0",
|
||||
"fb-watchman": "^2.0.0",
|
||||
"fsevents": "^1.2.7",
|
||||
"graceful-fs": "^4.1.15",
|
||||
"invariant": "^2.2.4",
|
||||
"jest-serializer": "^24.9.0",
|
||||
@ -18092,8 +18095,7 @@
|
||||
"dependencies": {
|
||||
"chokidar": "^3.4.1",
|
||||
"graceful-fs": "^4.1.2",
|
||||
"neo-async": "^2.5.0",
|
||||
"watchpack-chokidar2": "^2.0.1"
|
||||
"neo-async": "^2.5.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"watchpack-chokidar2": "^2.0.1"
|
||||
@ -18467,7 +18469,6 @@
|
||||
"anymatch": "^2.0.0",
|
||||
"async-each": "^1.0.1",
|
||||
"braces": "^2.3.2",
|
||||
"fsevents": "^1.2.7",
|
||||
"glob-parent": "^3.1.0",
|
||||
"inherits": "^2.0.3",
|
||||
"is-binary-path": "^1.0.0",
|
||||
@ -22093,6 +22094,14 @@
|
||||
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==",
|
||||
"dev": true
|
||||
},
|
||||
"axios": {
|
||||
"version": "0.24.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz",
|
||||
"integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.14.4"
|
||||
}
|
||||
},
|
||||
"babel-code-frame": {
|
||||
"version": "6.26.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
|
||||
@ -26185,8 +26194,7 @@
|
||||
"follow-redirects": {
|
||||
"version": "1.14.5",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.5.tgz",
|
||||
"integrity": "sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA=="
|
||||
},
|
||||
"for-in": {
|
||||
"version": "1.0.2",
|
||||
|
@ -9,6 +9,7 @@
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.24.0",
|
||||
"core-js": "^3.6.5",
|
||||
"vue": "^2.6.11",
|
||||
"vue-router": "^3.2.0",
|
||||
|
@ -1,48 +1,63 @@
|
||||
<template>
|
||||
<v-container>
|
||||
<h1 class="title font-weight-thin">Wyszukiwarka samochodów</h1>
|
||||
<v-row>
|
||||
<v-col md="3" v-for="item in items" :key="item.label">
|
||||
<v-combobox v-model="item.selected" :items="item.items" :label="item.label"></v-combobox>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row justify="center">
|
||||
<v-btn rounded color="primary" dark>Szukaj</v-btn>
|
||||
</v-row>
|
||||
</v-container>
|
||||
<v-container>
|
||||
<h1 class="title font-weight-thin">Wyszukiwarka samochodów</h1>
|
||||
<v-row>
|
||||
<v-col md="3" v-for="item in items" :key="item.label">
|
||||
<v-combobox
|
||||
v-model="item.selected"
|
||||
:items="item.items"
|
||||
:label="item.label"
|
||||
></v-combobox>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row justify="center">
|
||||
<v-btn rounded color="primary" dark @click="send">Szukaj</v-btn>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from "axios";
|
||||
import { mapMutations } from 'vuex'
|
||||
export default {
|
||||
name: "Search",
|
||||
name: "Search",
|
||||
|
||||
data: () => ({
|
||||
items: {
|
||||
age: {
|
||||
label: "Rok produkcji",
|
||||
selected: "",
|
||||
items: ["Dawno", "Średnio", "Niedawno"],
|
||||
},
|
||||
mileage: {
|
||||
label: "Przebieg",
|
||||
selected: "",
|
||||
items: ["Niski", "Średni", "Duży"],
|
||||
},
|
||||
engine_capacity: {
|
||||
label: "Pojemność silnika",
|
||||
selected: "",
|
||||
items: ["Mała", "Średnia", "Ogromna"],
|
||||
},
|
||||
fuel_usage: {
|
||||
label: "Spalanie paliwa",
|
||||
selected: "",
|
||||
items: ["Niskie", "Średnie", "Wysokie"],
|
||||
},
|
||||
},
|
||||
}),
|
||||
data: () => ({
|
||||
items: {
|
||||
production_year: {
|
||||
label: "Rok produkcji",
|
||||
selected: "",
|
||||
items: ["Dawno", "Średnio", "Niedawno"],
|
||||
},
|
||||
mileage: {
|
||||
label: "Przebieg",
|
||||
selected: "",
|
||||
items: ["Niski", "Średni", "Duży"],
|
||||
},
|
||||
engine_capacity: {
|
||||
label: "Pojemność silnika",
|
||||
selected: "",
|
||||
items: ["Mała", "Średnia", "Ogromna"],
|
||||
},
|
||||
combustion: {
|
||||
label: "Spalanie paliwa",
|
||||
selected: "",
|
||||
items: ["Niskie", "Średnie", "Wysokie"],
|
||||
},
|
||||
},
|
||||
}),
|
||||
methods: {
|
||||
...mapMutations(['setCars']),
|
||||
send() {
|
||||
let query = {}
|
||||
Object.entries(this.items).forEach(([key, value]) =>
|
||||
query[key] = value.selected
|
||||
);
|
||||
axios.get('http://localhost:8000/cars', { params: query}).then((res) => { this.setCars(res.data) })
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
|
@ -2,13 +2,14 @@
|
||||
<v-container>
|
||||
<v-row>
|
||||
<v-col md="12">
|
||||
<v-data-table :headers="headers" :items="items" class="elevation-1"></v-data-table>
|
||||
<v-data-table :headers="headers" :items="getCars" class="elevation-1"></v-data-table>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
export default {
|
||||
name: "Table",
|
||||
|
||||
@ -19,7 +20,7 @@ export default {
|
||||
{ text: "Przebieg (km)", value: "mileage" },
|
||||
{ text: "Rok produkcji", value: "production_year" },
|
||||
{ text: "Pojemnośc silnika (cm^3)", value: "engine_capacity" },
|
||||
{ text: "Spalanie (L/100km)", value: "fuel_usage" },
|
||||
{ text: "Spalanie (L/100km)", value: "combustion" },
|
||||
{ text: "Cena (zł)", value: "price" },
|
||||
],
|
||||
items: [{
|
||||
@ -28,7 +29,7 @@ export default {
|
||||
mileage: 230000,
|
||||
production_year: 2008,
|
||||
engine_capacity: 2.0,
|
||||
fuel_usage: 7.6,
|
||||
combustion: 7.6,
|
||||
price: 12200,
|
||||
},
|
||||
{
|
||||
@ -37,11 +38,14 @@ export default {
|
||||
mileage: 430000,
|
||||
production_year: 2003,
|
||||
engine_capacity: 1.3,
|
||||
fuel_usage: 5.5,
|
||||
combustion: 5.5,
|
||||
price: 3500,
|
||||
},
|
||||
],
|
||||
}),
|
||||
computed: {
|
||||
...mapGetters(['getCars'])
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
@ -4,8 +4,19 @@ import Vuex from "vuex";
|
||||
Vue.use(Vuex);
|
||||
|
||||
export default new Vuex.Store({
|
||||
state: {},
|
||||
mutations: {},
|
||||
state: {
|
||||
cars: []
|
||||
},
|
||||
mutations: {
|
||||
setCars(state, cars) {
|
||||
state.cars = cars
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
getCars: state => {
|
||||
return state.cars
|
||||
}
|
||||
},
|
||||
actions: {},
|
||||
modules: {},
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user