diff --git a/.idea/dataSources.local.xml b/.idea/dataSources.local.xml new file mode 100644 index 0000000000000000000000000000000000000000..724f43e912927e5ea50eccd53ef4979c211313bd --- /dev/null +++ b/.idea/dataSources.local.xml @@ -0,0 +1,13 @@ + + + + + + " + + + false + *:@ + + + \ No newline at end of file diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml new file mode 100644 index 0000000000000000000000000000000000000000..289dfb7dc7a308d9deba98c5bf70d5fb65f6d80f --- /dev/null +++ b/.idea/dataSources.xml @@ -0,0 +1,22 @@ + + + + + sqlite.xerial + true + org.sqlite.JDBC + jdbc:sqlite:F:\django-restframework-test\db.sqlite3 + + + + + + file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.31.1/license.txt + + + file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.31.1/sqlite-jdbc-3.31.1.jar + + + + + \ No newline at end of file diff --git a/.idea/dataSources/7f0a39cb-1ee2-461b-a29c-eb6f63c17473.xml b/.idea/dataSources/7f0a39cb-1ee2-461b-a29c-eb6f63c17473.xml new file mode 100644 index 0000000000000000000000000000000000000000..8131940e2f004df59db3078f647ff7393a121623 --- /dev/null +++ b/.idea/dataSources/7f0a39cb-1ee2-461b-a29c-eb6f63c17473.xml @@ -0,0 +1,575 @@ + + + + + 3.31.1 + + + 1 + 1 + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+ 1 +
+ + 1 +
+ + 1 + integer|0s + 1 + 1 + + + 2 + varchar(80)|0s + 1 + + + 1 + name + + 1 + + + id + 1 + + + name + sqlite_autoindex_auth_group_1 + + + 1 + integer|0s + 1 + 1 + + + 2 + integer|0s + 1 + + + 3 + integer|0s + 1 + + + group_id +permission_id + + 1 + + + group_id + + + + permission_id + + + + id + 1 + + + group_id + auth_group + id + 1 + 1 + + + permission_id + auth_permission + id + 1 + 1 + + + 1 + integer|0s + 1 + 1 + + + 2 + integer|0s + 1 + + + 3 + varchar(100)|0s + 1 + + + 4 + varchar(255)|0s + 1 + + + content_type_id +codename + + 1 + + + content_type_id + + + + id + 1 + + + content_type_id + django_content_type + id + 1 + 1 + + + 1 + integer|0s + 1 + 1 + + + 2 + varchar(128)|0s + 1 + + + 3 + datetime|0s + + + 4 + bool|0s + 1 + + + 5 + varchar(150)|0s + 1 + + + 6 + varchar(30)|0s + 1 + + + 7 + varchar(254)|0s + 1 + + + 8 + bool|0s + 1 + + + 9 + bool|0s + 1 + + + 10 + datetime|0s + 1 + + + 11 + varchar(150)|0s + 1 + + + 1 + username + + 1 + + + id + 1 + + + username + sqlite_autoindex_auth_user_1 + + + 1 + integer|0s + 1 + 1 + + + 2 + integer|0s + 1 + + + 3 + integer|0s + 1 + + + user_id +group_id + + 1 + + + user_id + + + + group_id + + + + id + 1 + + + user_id + auth_user + id + 1 + 1 + + + group_id + auth_group + id + 1 + 1 + + + 1 + integer|0s + 1 + 1 + + + 2 + integer|0s + 1 + + + 3 + integer|0s + 1 + + + user_id +permission_id + + 1 + + + user_id + + + + permission_id + + + + id + 1 + + + user_id + auth_user + id + 1 + 1 + + + permission_id + auth_permission + id + 1 + 1 + + + 1 + integer|0s + 1 + 1 + + + 2 + datetime|0s + 1 + + + 3 + text|0s + + + 4 + varchar(200)|0s + 1 + + + 5 + text|0s + 1 + + + 6 + integer|0s + + + 7 + integer|0s + 1 + + + 8 + smallint unsigned|0s + 1 + + + content_type_id + + + + user_id + + + + id + 1 + + + content_type_id + django_content_type + id + 1 + 1 + + + user_id + auth_user + id + 1 + 1 + + + 1 + integer|0s + 1 + 1 + + + 2 + varchar(100)|0s + 1 + + + 3 + varchar(100)|0s + 1 + + + app_label +model + + 1 + + + id + 1 + + + 1 + integer|0s + 1 + 1 + + + 2 + varchar(255)|0s + 1 + + + 3 + varchar(255)|0s + 1 + + + 4 + datetime|0s + 1 + + + id + 1 + + + 1 + varchar(40)|0s + 1 + + + 2 + text|0s + 1 + + + 3 + datetime|0s + 1 + + + 1 + session_key + + 1 + + + expire_date + + + + session_key + 1 + sqlite_autoindex_django_session_1 + + + 1 + integer|0s + 1 + 1 + + + 2 + varchar(255)|0s + + + id + 1 + + + 1 + integer|0s + 1 + 1 + + + 2 + varchar(255)|0s + + + 3 + integer|0s + 1 + + + 4 + real|0s + 1 + + + 5 + date|0s + 1 + + + 6 + integer|0s + 1 + + + 7 + integer|0s + 1 + + + author_id + + + + category_id + + + + id + 1 + + + author_id + library_app_author + id + 1 + 1 + + + category_id + library_app_category + id + 1 + 1 + + + 1 + integer|0s + 1 + 1 + + + 2 + varchar(100)|0s + + + id + 1 + + + 1 + text|0s + + + 2 + text|0s + + + 3 + text|0s + + + 4 + int|0s + + + 5 + text|0s + + + 1 + + + 2 + +
+
\ No newline at end of file diff --git a/.idea/django-restframework-test.iml b/.idea/django-restframework-test.iml new file mode 100644 index 0000000000000000000000000000000000000000..613a277b7b491a47c92a94c28635cdc1ef902ee7 --- /dev/null +++ b/.idea/django-restframework-test.iml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000000000000000000000000000000000000..c79f534732d432a816f0e51c0f575c3bee81586f --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000000000000000000000000000000000000..1889bab237d621b9c36a18b3e1e08de49494f49b --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000000000000000000000000000000000000..94a25f7f4cb416c083d265558da75d457237d671 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000000000000000000000000000000000000..ea9cbdbe1c99df457c8a2dc265e4d8b68f53889e --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,410 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1610764951889 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index 31bfddb6f1ba67d096c12cd779f2056b4549434b..f85f4fe194f39cd2675671b23f54d34852526534 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,79 @@ -# Coding challenge - API +# 一、错误 +## 错误一: + 运行项目报: + File "F:\django-restframework-test\library_app\serializers.py", line 13, in BookReadSerializer + category = CategorySerializer() + NameError: name 'CategorySerializer' is not defined +## 原因与解决: + 原因:因为在CategorySerializer被创建前调用该方法,所以出现此问题 + 解决:将CategorySerializer的创建提前到调用之前 + +## 错误二: + 访问book表报错: + __str__ returned non-string (type NoneType) +## 原因与解决 + 解决: + 重新运行了一下 + python manage.py makemigrations + python manage.py migrate + 即恢复正常 + 原因: + 可能是原项目之前修改表后未修改数据库 -We'd like to extend this Django REST Framework project (based on the one found -[here](https://github.com/beheshtraya/django_rest_sample)). +# 二、需求 + ## 1.Total number of books owned.(拥有的图书总数) +```python +def books_num(request): + #书本总数 + json_str={ + "count":Book.objects.all().count()#查表计数 + } + return HttpResponse(json.dumps(json_str))#返回json数据 +``` + ## 2.Total cost of all books.(所有书籍的总费用。) +```python +def books_cost(request): + #书本总价 + total_list=[ i["price"] for i in list(Book.objects.all().values('price'))] #查表价格 + json_str={ + "info":sum(total_list) #求和价格 + } + return HttpResponse(json.dumps(json_str))#返回json数据 -The API stores information about authors, categories and books. +``` + ## 3.Author with most books.(写书最多的作者。) +```python +from collections import Counter +def mostAuthor(request): + #最多的作者 + total_list=[ i["author"] for i in list(Book.objects.all().values('author'))]#查表作者 + count = Counter(total_list)#统计作者 + max_prices = max(zip(count.values(), count.keys()))#最多的作者序号 + most_num=Author.objects.all()[max_prices[1]-1]#查作者表,取作者 + print(most_num) + json_str={ + "info":str(most_num) + } + return HttpResponse(json.dumps(json_str))#返回json数据 -We'd like to let our API users view library statistics, namely: +``` + ## 4.Category with most books.(最多的分类。) +```python +from collections import Counter +def mostCategory(request): + #最多的分类 + total_list=[ i["category"] for i in list(Book.objects.all().values('category'))]#查表分类 + count = Counter(total_list)#统计分类 + max_prices = max(zip(count.values(), count.keys()))#最多的序号 + most_num=Category.objects.all()[max_prices[1]-1]#查分类表,取分类 + print(most_num) + json_str={ + "info":str(most_num) + } + return HttpResponse(json.dumps(json_str))#返回json数据 +``` - 1. Total number of books owned. - 2. Total cost of all books. - 3. Author with most books. - 4. Category with most books. + -There are a few ways to approach this; feel free to choose one that seems -appropriate, and please explain why you think it's best for us. - -We've also heard of at least one bug in the codebase. Can you try to identify -issues in the existing code, and document how you discovered and fixed the -bugs? - -Also: - - - Please treat all code as production level code. - - Please don’t spend more than 4 hours on this. If time runs short, an - explanation of what you would do given more time is fine. - -## Original `readme.txt` - - > pip install -r requirements.txt - > python manage.py makemigrations - > python manage.py migrate - > python manage.py runserver - -- server will be run on 127.0.0.1:8000 + + \ No newline at end of file diff --git a/README_old.md b/README_old.md new file mode 100644 index 0000000000000000000000000000000000000000..31bfddb6f1ba67d096c12cd779f2056b4549434b --- /dev/null +++ b/README_old.md @@ -0,0 +1,34 @@ +# Coding challenge - API + +We'd like to extend this Django REST Framework project (based on the one found +[here](https://github.com/beheshtraya/django_rest_sample)). + +The API stores information about authors, categories and books. + +We'd like to let our API users view library statistics, namely: + + 1. Total number of books owned. + 2. Total cost of all books. + 3. Author with most books. + 4. Category with most books. + +There are a few ways to approach this; feel free to choose one that seems +appropriate, and please explain why you think it's best for us. + +We've also heard of at least one bug in the codebase. Can you try to identify +issues in the existing code, and document how you discovered and fixed the +bugs? + +Also: + + - Please treat all code as production level code. + - Please don’t spend more than 4 hours on this. If time runs short, an + explanation of what you would do given more time is fine. + +## Original `readme.txt` + + > pip install -r requirements.txt + > python manage.py makemigrations + > python manage.py migrate + > python manage.py runserver + -- server will be run on 127.0.0.1:8000 diff --git a/db.sqlite3 b/db.sqlite3 index 42db1a76d95f421c660bd03c45f143554cb13386..81d36904d1aa11721f45ae3c0450ed3784fbc507 100644 Binary files a/db.sqlite3 and b/db.sqlite3 differ diff --git a/django_rest_sample/settings.py b/django_rest_sample/settings.py index a6dc00d37c5b630e939cc8df79bf81cf1f3b86d5..0fe97153813b0e0776b2d6a87a7da4b8c41a3e04 100644 --- a/django_rest_sample/settings.py +++ b/django_rest_sample/settings.py @@ -122,6 +122,9 @@ USE_TZ = True STATIC_URL = '/static/' +LANGUAGE_CODE = 'zh-hans' + +TIME_ZONE = 'Asia/Shanghai' REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', diff --git a/django_rest_sample/urls.py b/django_rest_sample/urls.py index 05fb841da371ccc55cbe81f3dacc6687bba81312..f98b444464ef9ef29d5a7bcb9b1acc2c06ccc54a 100644 --- a/django_rest_sample/urls.py +++ b/django_rest_sample/urls.py @@ -14,7 +14,7 @@ Including another URLconf 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ from django.contrib import admin -from django.urls import path +from django.urls import path,include from rest_framework import routers from library_app.views import BookViewSet, CategoryViewSet, AuthorViewSet @@ -26,5 +26,6 @@ router.register(r'authors', AuthorViewSet) urlpatterns = router.urls urlpatterns += [ + path('book_num/', include('library_app.urls')), path('admin/', admin.site.urls), ] diff --git a/library_app/models.py b/library_app/models.py index 4efae69f4620109b96b6cacc7c3809592f8bbc5c..3931839eb3fe1b94f1ca4485c71581f05f474866 100644 --- a/library_app/models.py +++ b/library_app/models.py @@ -10,7 +10,9 @@ class Book(models.Model): publish_date = models.DateField() def __str__(self): - return self.title + return str(self.title) + + class Author(models.Model): name = models.CharField(max_length=255, null=True, blank=True) diff --git a/library_app/serializers.py b/library_app/serializers.py index 849aea1f7cfdf51d36afe7743319ac57b0688bc5..d677533d7398588afaf462bd686b084130d9ca41 100644 --- a/library_app/serializers.py +++ b/library_app/serializers.py @@ -2,6 +2,10 @@ from rest_framework import serializers from library_app.models import Category, Book, Author +class CategorySerializer(serializers.ModelSerializer): + class Meta: + model = Category + fields = "__all__" class AuthorSerializer(serializers.ModelSerializer): @@ -13,6 +17,7 @@ class BookReadSerializer(serializers.ModelSerializer): category = CategorySerializer() author = AuthorSerializer() + class Meta: model = Book fields = '__all__' @@ -22,7 +27,3 @@ class BookWriteSerializer(serializers.ModelSerializer): model = Book fields = "__all__" -class CategorySerializer(serializers.ModelSerializer): - class Meta: - model = Category - fields = "__all__" diff --git a/library_app/urls.py b/library_app/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..d792981e8bf64b029cd59a753e4772436c09a93b --- /dev/null +++ b/library_app/urls.py @@ -0,0 +1,10 @@ +from django.urls import path + +from . import views + +urlpatterns = [ + path('', views.books_num, name='books_num'), + path('books_cost', views.books_cost, name='books_cost'), + path('mostAuthor', views.mostAuthor, name='mostAuthor'), + path('mostCategory', views.mostCategory, name='mostCategory'), +] \ No newline at end of file diff --git a/library_app/views.py b/library_app/views.py index da56ab7fe376dc3d778ee7e3d280b4971270631d..8f78d76a305defeaa9c1fefedcd64ab7277aa3cd 100644 --- a/library_app/views.py +++ b/library_app/views.py @@ -1,12 +1,55 @@ +from django.http import HttpResponse from rest_framework import viewsets from library_app.models import Category, Author, Book from library_app.serializers import CategorySerializer, AuthorSerializer, BookReadSerializer, BookWriteSerializer +import json +from collections import Counter + + +def books_num(request): + #书本总数 + json_str={ + "count":Book.objects.all().count() + } + return HttpResponse(json.dumps(json_str)) + +def books_cost(request): + #书本总价 + total_list=[ i["price"] for i in list(Book.objects.all().values('price'))] + json_str={ + "total_books_cost":sum(total_list) + } + return HttpResponse(json.dumps(json_str)) + +def mostAuthor(request): + #最多的作者 + total_list=[ i["author"] for i in list(Book.objects.all().values('author'))] + count = Counter(total_list) + max_prices = max(zip(count.values(), count.keys())) + most_num=Author.objects.all()[max_prices[1]-1] + print(most_num) + json_str={ + "total_books_cost":str(most_num) + } + return HttpResponse(json.dumps(json_str)) + +def mostCategory(request): + #最多的分类 + total_list=[ i["category"] for i in list(Book.objects.all().values('category'))] + count = Counter(total_list) + max_prices = max(zip(count.values(), count.keys())) + most_num=Category.objects.all()[max_prices[1]-1] + print(most_num) + json_str={ + "total_books_cost":str(most_num) + } + return HttpResponse(json.dumps(json_str)) + class BookViewSet(viewsets.ModelViewSet): queryset = Book.objects.all() - def get_serializer_class(self): if self.request.method in ['GET', 'HEAD']: return BookReadSerializer