Django rest_frameword 之项目流程
后端开发软件目录规范
一.Model
from django.db import models # Create your models here. # 多表的设计 # 图书 作者 出版社 作者详情表 # 基表的创建主要是我们的字段都有共同的字段抽离 class BaseModel(models.Model): # 相同的字段 is_delete = models.BooleanField(default=False) create_time = models.DateTimeField(auto_now_add=True) # 在建基表的时候要设置 abs 来声明基表,作为基表的model 不能再数据库中行成对应的表 class Meta: abstract = True class Book(BaseModel): name = models.CharField(max_length=32) price = models.DecimalField(max_digits=8, decimal_places=2) img = models.ImageField(upload_to='img', default='img/default.jpg/') # 外键字段的建表规则健在查询频率少的那张表 效率的问题 # 多对对外键健在那张表都可以 authors = models.ManyToManyField(to='Author', db_constraint=False, related_name='books') publisher = models.ForeignKey( to='Publish', related_name='books', # 反向查字典的关键字publish_obj.books就能访问改出版社的所有书籍 on_delete=models.DO_NOTHING, db_constraint=False) class Meta: db_table = 'book' verbose_name = '书籍表' verbose_name_plural = verbose_name @property def author_list(self): # 查表 作者有多个值的 return self.authors.values('name', 'age','detail__addr','detail__phone').all() @property def publish_name(self): # 正向按字段 return self.publisher.name def __str__(self): return "<%s>" % self.name class Author(BaseModel): name = models.CharField(max_length=32) age = models.IntegerField() class Meta: db_table = 'author' verbose_name = '作者表' verbose_name_plural = verbose_name def __str__(self): return "%s" % self.name class Publish(BaseModel): name = models.CharField(max_length=32) addr = models.CharField(max_length=32) class Meta: db_table = 'publish' verbose_name = '出版社表' verbose_name_plural = verbose_name def __str__(self): return "%s" % self.name class AuthorDetail(BaseModel): addr = models.CharField(max_length=32) phone = models.CharField(max_length=11, null=True) # 外键字段一对多还是建立多方 # 一对一就健在查询评率低的一方 # 一对一的cascade是同步的进行同删同减 author_detail = models.OneToOneField(to='Author', db_constraint=False, related_name='detail', on_delete=models.CASCADE) class Meta: db_table = 'author_detail' verbose_name = '详情表' verbose_name_plural = verbose_name def __str__(self): return "%s" % self.author_detail.name
api 或者项目名下的__init__
import pymysql pymysql.install_as_MySQLdb()
二.settings
数据库和全局文件的配置 图片的暴露接口
""" Django settings for day71_djproj project. Generated by 'django-admin startproject' using Django 1.11.11. For more information on this file, see https://docs.djangoproject.com/en/1.11/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/1.11/ref/settings/ """ import os # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = '^zqxsy^v6z)!9klipb^^3@=txceu7^b4!-rsp#8r55&_u^p11h' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'api.apps.ApiConfig', 'rest_framework' ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] ROOT_URLCONF = 'day71_djproj.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')] , 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] WSGI_APPLICATION = 'day71_djproj.wsgi.application' # Database # https://docs.djangoproject.com/en/1.11/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'day71_dj', 'USER': "root", ', 'HOST':"127.0.0.1", 'PORT': 3306 } } # Password validation # https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # Internationalization # https://docs.djangoproject.com/en/1.11/topics/i18n/ LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = False # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/1.11/howto/static-files/ STATIC_URL = '/static/' # 图片 MEDIA_URL = '/media/' # 图片的更目录的配置 MEDIA_ROOT = os.path.join(BASE_DIR,'/media/') # 我们还要配置解析的全局配置文件 如果想要配置局部的就要在我们自己的类函数下进行配置 方法 # 配置响应的全局文件 # 配置自定义的异常文件的全局的配置 # 自定义drf配置爱-全局响应配置 REST_FRAMEWORK = { # drf提供的渲染类 'DEFAULT_RENDERER_CLASSES': [ 'rest_framework.renderers.JSONRenderer', 'rest_framework.renderers.BrowsableAPIRenderer', ], # drf提供类解析的数据包的格式 请求格式 再取全局进行配置 全局 进而进行局部的的设置 'DEFAULT_PARSER_CLASSES': [ 'rest_framework.parsers.JSONParser', 'rest_framework.parsers.FormParser', 'rest_framework.parsers.MultiPartParser', ], # 全局配置异常模块 自定有异常模块 'EXCEPTION_HANDLER': 'api.exception.exception_handler', }
准备事项配置好后 model 表的迁移命令
(1)
D:\day71_djproj>python manage.py makemigrations
(2)python manage.py migrate
或者快捷键
三.admin
注册超级用户 createsuperuser()
将我们的model 模型表一一注册到我们的admin 中>>> 数据的新增 (方便测试)
from django.contrib import admin from api import models # Register your models here. admin.site.register(models.Author) admin.site.register(models.Book) admin.site.register(models.AuthorDetail) admin.site.register(models.Publish)
四.URL 路由的匹配
(1)总路由 >>>实现陆游的分发
from django.conf.urls import url, include from django.contrib import admin # from django.conf.urls import url # 资源暴露给外部 必须配置在全局的 # 渲染图片 接口暴露给外部\ from day71_djproj import settings from django.views.static import serve urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^api/', include('api.urls')), url(r'^media/(?P<path>.*)', serve, {'document_root':settings.MEDIA_ROOT}), ]
(2)项目api下的路由
from django.conf.urls import url from api import views # 路由模块:为标准的viweset接口提供路径的简写方式 from django.conf.urls import include from rest_framework.routers import SimpleRouter router = SimpleRouter() # 路径对象进注册 router.register('v6/books',views.BookModelViewSet) urlpatterns = [ url(r'^books/$',views.V2Book.as_view()), url(r'^books/(?P<pk>.*)/$',views.V2Book.as_view()), url(r"^v1/books/$",views.BookApIView.as_view()), url(r"^v1/books/(?P<pk>.*)/$", views.BookApIView.as_view()), url(r"^v2/books/$", views.BookGenericAPIView.as_view()), url(r'^v2/books/(?P<pk>.*)/$', views.BookGenericAPIView.as_view()), url(r"^v3/books/$", views.BookMixinGenericAPIView.as_view()), url(r'^v3/books/(?P<pk>.*)/$', views.BookMixinGenericAPIView.as_view()), url(r"^v4/books/$", views.BookListCreateAPIView.as_view()), url(r'^v4/books/(?P<pk>.*)/$', views.BookListCreateAPIView.as_view()), url(r"^v5/books/$", views.BookGenericViewSet.as_view({"get": "my_get_list"})), url(r'^v5/books/(?P<pk>.*)/$', views.BookGenericViewSet.as_view({"get": "my_get_obj"})), url(r"^vv/books/$", views.MyRequest.as_view()), url(r'^vv/books/(?P<pk>.*)/$', views.MyRequest.as_view()), url(r'^v7/books/$',views.BookModelViewSet.as_view({"get":'list','post':'create'})), url(r'^v7/books/(?P<pk>.*)/$',views.BookModelViewSet.as_view({'get':'retrieve','put':'update','patch':'partial_update','delete':'destroy'})), # 在下面进行分发应用匹配 url(r'^',include(router.urls)) ]
五.视图函数
from django.shortcuts import render from . import serializers from api import models # Create your views here. from rest_framework.views import APIView from rest_framework.response import Response from utils.response import APIResponse class V2Book(APIView): # 单查 # 群查 def get(self, request, *args, **kwargs): # print(request.query_params,12312) pk = kwargs.get('pk') if pk: try: book_obj = models.Book.objects.get(pk=pk, is_delete=False) print(book_obj, type(book_obj), 3212) book_data = serializers.BookModelSerializer(book_obj).data # print(book_data,type(book_data),123) return Response({ 'status': 1, 'msg': 'ok', 'results': book_data }) except: return Response({ "status": 0, 'img': "数据有误" }) else: book_query = models.Book.objects.filter(is_delete=False).all() book_data = serializers.BookModelSerializer(book_query, many=True).data return Response({ 'status': 1, 'msg': 'ok', 'results': book_data }) # 反序列化的 通过序列化组件 # user_ser = serializer def post(self, request, *args, **kwargs): # 单增数据是与model对应的字典 获取的数据的格式和类型的检验 request_data = request.data print(request_data) # if not isinstance(request_data,dict) or request_data == {}: # return Response({ # 'status': 1, # 'msg': '数据有误', # # }) # else: # 单增 if isinstance(request_data, dict) and request_data != {}: many = False book_data = serializers.BookModelSerializer(data=request_data, many=many) # 进行反序列化的对象赋值 # 当前视图异常是 立即出发报错异常的进行返回到前端 book_data.is_valid(raise_exception=True) # 进行数据的检验 data_result = book_data.save() return Response({ 'status': 1, 'msg': 'ok', 'results': serializers.BookModelSerializer(data_result).data # 反序列化 }) elif isinstance(request_data, list) and request_data != []: # 是多个值的话 同时新增多个对象 many = True book_data = serializers.BookModelSerializer(data=request_data, many=many) # 反序列化 再存 book_data.is_valid(raise_exception=True) # 进行数据的检验 # ??? data_result = book_data.save() return Response({ 'status': 1, 'msg': 'ok', 'results': serializers.BookModelSerializer(data_result, many=many).data # 反序列化 }) else: return Response({ 'status': 0, 'msg': '数据格式有误' }) # 获取数据 # 全增 def delete(self, request, *args, **kwargs): pk = kwargs.get('pk') if pk: # pk__in 符合下面的要求 pks = [pk] else: pks = request.data.get('pks') if models.Book.objects.filter(pk__in=pks, is_delete=False).update(is_delete=True): # 直接返回 return Response({ 'status': 1, 'msg': '删除成功' }) else: return Response({ 'status': 0, 'msg': '删除未成功' }) def put(self, request, *args, **kwargs): # 单 整体修改 # 序列化的是对象 pk = kwargs.get('pk') book_obj = models.Book.objects.filter(pk=pk).first() # 反序列化 数据 request_data = request.data # 反序列化的对数据进行修改的三件事 1.数据是改谁的 2.将数据进行data 封装 3.完序列化后的数据的检验 # 反序列化的是传的对象的 和值 book_ser = serializers.BookModelSerializer(instance=book_obj, data=request_data, ) # 反序列化传数据 还需要修改的对象 # 检验 book_ser.is_valid(raise_exception=True) # 修改入库 result_obj = book_ser.save() # 修改入库 return Response({ 'status': 1, 'msg': '修改成功', # 返回的 是序列化对象 传入的是save() 返回的对象 'results': serializers.BookModelSerializer(result_obj).data }) # 进行单改和全改的patch() # 单体pk = [1,] # 多改pk=[1,2,3] def patch(self, request, *args, **kwargs): pk = kwargs.get("pk") request_data = request.data # 单改 if pk and isinstance(request_data, dict): pks = [pk, ] request_data = [request_data, ] # 群改 elif not pk and isinstance(request_data, list): pks = [] # for data in request_data: # 将每个数据中的字典进行删除(本质是返回键) pk = data.pop('pk', None) if pk: pks.append(pk) else: return Response({ 'status': 0, 'msg': '数据有误' }) else: return Response({ "status": 0, 'msg': "数据有误" }) # 将上面的单改和群对象改进行逻辑业务处理 # 我们需要处理的是pks中 and健值绑定的没有数据的pks 进行删除 # 将合理的数据进保存 objs = [] new_data = [] for index, pk in enumerate(pks): try: # 存储合理的数据进行修改 obj = models.Book.objects.get(pk=pk, is_delete=False) # BUG objs.append(obj) # 将对应上的数据保存 new_data.append(request_data[index]) except: # 继续循环 循环结束继续结束 continue # 统一的逻辑 book_ser = serializers.BookModelSerializer(instance=objs, data=new_data, partial=True, many=True) # 校验 book_ser.is_valid(raise_exception=True) print(book_ser, 123) book_obj = book_ser.save() print(book_obj, 555) # 返回 return Response({ 'status': 1, 'msg': '修改成功', # 序列化和反序列化只要有多个必须是many = TRUE 'results': serializers.BookModelSerializer(book_obj, many=True).data }) # 重写response() 响应方法 class BookApIView(APIView): def get(self, *args, **kwargs): book_query = models.Book.objects.filter(is_delete=False).all() book_ser = serializers.BookModelSerializer(book_query, many=True) # print(book_ser) book_data = book_ser.data # 数据是存放在data 中的 # print(book_data) # 返回数据我们用封装号的 return APIResponse(results=book_data) # Genseric 类 from rest_framework.generics import GenericAPIView class BookGenericAPIView(GenericAPIView): # 因为我们继承的是GenericAPIView >>> 继承APIView # queryset = None 和serializer = None 初始值为空时需要我们进行重写的 queryset = models.Book.objects.filter(is_delete=False) serializer_class = serializers.BookModelSerializer # 单查 pk get的方法 lookup_field = 'pk' # def get(self, request, *args, **kwargs): # book_query = self.get_object() # print(book_query, 55) # book_ser = self.get_serializer(book_query) # book_data = book_ser.data # return APIResponse(results=book_data) # 群查 def get(self, request, *args, **kwargs): book_query = self.get_queryset() book_ser = self.get_serializer(book_query,many=True) # 这里加上many=True book_data = book_ser.data return APIResponse(results=book_data) """ # 1)mixins有五个工具类文件,一共提供了五个工具类,六个工具方法:单查、群查、单增、单删、单整体改、单局部改 # 2)继承工具类可以简化请求函数的实现体,但是必须继承GenericAPIView,需要GenericAPIView类提供的几个类属性和方法(见上方GenericAPIView基类知识点) # 3)工具类的工具方法返回值都是Response类型对象,如果要格式化数据格式再返回给前台,可以通过 response.data 拿到工具方法返回的Response类型对象的响应数据 """ # mixins 有五大工具六大方法 from rest_framework.mixins import ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin class BookMixinGenericAPIView(ListModelMixin,CreateModelMixin,UpdateModelMixin,RetrieveModelMixin,GenericAPIView): # 先获取对象 queryset = models.Book.objects.filter(is_delete=False) # 重写序列化 serializer_class = serializers.BookModelSerializer # get 查询 def get(self,request,*args, **kwargs): # mixins 中的单查 pk if 'pk' in kwargs: response = self.retrieve(request,*args,**kwargs) else: # mixins提供的list方法的响应对象是Response,想将该对象格式化为APIResponse response = self.list(request, *args, **kwargs) # 数据都是封装在response return APIResponse(results=response.data) # 单增post 多增的操作 def post(self, request, *args, **kwargs): response = self.create(request, *args, **kwargs) return APIResponse(results=response.data) # =更新put # 注意必须在pk = 22 有值的情况 也必须是在url 中拼接pk 才能进行目前的修改 def put(self,request, *args, **kwargs): response = self.update(request, *args, **kwargs) return APIResponse(results=response.data) # patch修改 也会需要 pk url 中拼接 def patch(self,request, *args, **kwargs): response = self.update(request, *args, **kwargs) return APIResponse(results=response.data) # 工具视图 """ # 1)工具视图都是GenericAPIView的子类,且不同的子类继承了不听的工具类,重写了请求方法 # 2)工具视图的功能如果直接可以满足需求,只需要继承工具视图,提供queryset与serializer_class即可 """ # 群查 局部更新 from rest_framework.generics import ListCreateAPIView,UpdateAPIView class BookListCreateAPIView(ListCreateAPIView, UpdateAPIView): queryset = models.Book.objects.filter(is_delete=False) serializer_class = serializers.BookModelSerializer # 视图集..set """ (1)优先继承ViewSetMixin 类 再继承一个视图类(GenericViewSet 和APIView) (2)ViewSetMixin提供重写ad_view() 方法 ,继承视图集的属兔类,-匹配路由调用da_view() 必须出入对饮的映射关系as_view("get":"my_get_list") """ from rest_framework.viewsets import GenericViewSet # 视图集中导入视图类 from rest_framework import mixins # 工具类 class BookGenericViewSet(mixins.RetrieveModelMixin, mixins.ListModelMixin, GenericViewSet): queryset = models.Book.objects.filter(is_delete=False) serializer_class = serializers.BookModelSerializer # 群查 def my_get_list(self,request,*args, **kwargs): return self.list(request, *args, **kwargs) # 单查 def my_get_obj(self, request,*args, **kwargs): return self.retrieve(request, *args, **kwargs) class MyRequest(APIView): def post(self, request, *args, **kwargs): request_data = request.data # book_ser 序列化数据对象 book_data = serializers.BookModelSerializer(data=request_data, many=False, context={"request": request}) # 进行数据的检验 book_data.is_valid(raise_exception=True) result_data = book_data.save() return APIResponse(results=result_data) # 直接封装 create() 的话要进行many = True # 拥有就打接口:单查/群查/单增/ 单删/单整体改/单局部改 # 补充:一般肯定需要我们重写destroy 方法 """ class ModelViewSet(mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, mixins.ListModelMixin, GenericViewSet): # 继承这个主要是让他遵循我们自己写的as_view({"get":"list",'patch':"partial_update",'put':"update","post":"create", "destroy":'destroy'}) """ from rest_framework.viewsets import ModelViewSet class BookModelViewSet(ModelViewSet): queryset = models.Book.objects.filter(is_delete=False) serializer_class = serializers.BookModelSerializer """ as_view({"get":'list','post':'create'}) get >>>list 群查 post >>> 新增 as_view({'get':'retrieve','put':'update','patch':'partial_update','delete':'destroy'} get >>>retrieve 单查 提供pk在url put >>> partial = False不能进单个字段的修改 而是整体字段的更新 patch >>>> partial_update 默认partial = True, """ # 一般我们删除的不是真正的数据 而是将他的bOOL 改为1 /获取是Treu # 除了删除需要我们自己写 因为 特会将正真的数据进行删除肯定不合理 所以我们自己写优先走我们自己的 def destroy(self, request, *args, **kwargs): instance = self.get_object() # 单删 实列化对象 if not instance: # 改实例对象不存在 return APIResponse(0, '删除失败') instance.is_delete = True instance.save() return APIResponse(1,'删除成功')
六.serializer文件:对象 序列化 钩子函数
from rest_framework.serializers import ModelSerializer,SerializerMethodField from rest_framework.serializers import ListSerializer from rest_framework.exceptions import ValidationError from . import models # 重写我们update() 方法 # 重点将我们ListSerializer() class BookListSerializer(ListSerializer): def update(self, instance, validated_data): print(instance,111) # [<Book: <东游记9988>>, <Book: <西游记999>>, <Book: <南游记>>] print(validated_data,2222) # [{'name': '东游记88', 'price': Decimal('66.66')}, {'name': '西游记999', # 'price': Decimal('77.88')}, {'name': '南游记', 'price': Decimal('8.88')}] # 获取里面的所有数据 print(self.child,12312312) for index, obj in enumerate(instance): # 获取对象的索引和下标 self.child.update(obj,validated_data[index]) return instance # 返回对象 class BookModelSerializer(ModelSerializer): class Meta: model = models.Book # 映射 fields = ('name','price', 'img','author_list', 'publish_name','publisher','authors') extra_kwargs = { 'name':{ 'required':True, 'min_length':3, 'error_messages':{ 'required':'必填字段', 'min_length':'不能少于3位数字' } }, 'publisher':{ 'write_only':True, }, 'authors':{ 'write_only': True }, 'img':{ 'read_only':True, }, 'author_list':{ 'read_only':True }, 'publish_name':{ 'read_only':True } } # patch()方法是用save() # 方法进行数据的更新 但是没有进行update()方法的封装 需要我们自己 重写update() 方法 list_serializer_class = BookListSerializer # 局部勾子和全局钩子 def validate_name(self,value): # 书名不能有'si'字符 print(self.context,1111) if 'k' in value: # ??? raise ValidationError('该k书不能出版') return value # 全局钩子 def validate(self, attrs): publisher = attrs.get('publisher') name = attrs.get('name') if models.Book.objects.filter(name=name,publisher=publisher): raise ValidationError({'book':'该书已经存在'}) return attrs
七.Media 媒体文件
八. exception自定义用异常文件
from rest_framework.views import exception_handler as drf_exception_handler from rest_framework.views import Response from rest_framework import status def exception_handler(exc, context): # drf的exception_handler做基础处理 response = drf_exception_handler(exc, context) # 为空,自定义二次处理 if response is None: print('%s - %s - %s' % (context['view'], context['request'].method, exc)) return Response({ 'detail': '服务器错误' }, status=status.HTTP_500_INTERNAL_SERVER_ERROR, exception=True) return response
九.utils文件 自定义响应的数据格式 以及我们的自定义分页器
# 我们自定义from rest_framework.response import Response class APIResponse(Response): def __init__(self, data_status=1,data_msg='ok', results=None,http_status=None, headers=None,exception=False,*kwargs): # 我们需要返回的值 # data的初始信息: data = { 'status':data_status, 'msg':data_msg, } # data的响应数据体 # results 响应可能是False 0等数据 这些数据在我们设计的方法下是不合法的所以要进行过滤 if results is not None: data['results'] = results # 将请求后的字典内容进行更新 有则 data.update(kwargs) super().__init__(data=data,status=http_status,headers=headers,exception=exception)
待更新........
Django rest_frameword 之项目流程的更多相关文章
- django搭建简单开发项目流程(一)
1 搭建环境 sudo apt-get install python3-pip 安装pip3 sudo pip3 install virtualenv 安装虚拟环境 virtualenv -p pyt ...
- web理论知识--网页访问过程(附有Django的web项目访问流程)
当我们闲暇之余想上网看看新闻,或者看个电影,通常的操作是:打开电脑.打开浏览器.输入网址.浏览页面信息.点击自己感兴趣的连接......那么有没有想过,这些网页从哪里来的?过程中计算机又做了什么事情了 ...
- Django 小实例S1 简易学生选课管理系统 1 项目流程梳理与数据库设计
Django 小实例S1 简易学生选课管理系统 第1章--项目流程梳理与数据库设计 点击查看教程总目录 作者自我介绍:b站小UP主,时常直播编程+红警三,python1对1辅导老师. 1 项目流程梳理 ...
- Django——博客项目
博客项目 目前的目标是构建一个基于Django的前后端完整的博客系统,首先对项目流程整理如下: 1. 分析需求 1.1. 基于用户认证组件和Ajax实现登录验证 图形验证码核心代码: 模板: < ...
- BBS+Blog项目流程及补充知识点
项目流程: 1. 产品需求 (1)基于用户认证组件和Ajax实现登陆验证(图片验证码) (2)基于forms组件和Ajax实现注册功能 (3)设计系统首页(文章列表渲染) (4)设计个人站点页面 (5 ...
- Django Rest framework实现流程
目录 一 什么是restful架构 二 Django REST framework简介 三 Django REST framework原理 四 Django REST framework源码流程 五 ...
- Django运行方式及处理流程总结(转发)
之前在网上看过一些介绍Django处理请求的流程和Django源码结构的文章,觉得了解一下这些内容对开发Django项目还是很有帮助的.所以,我按照自己的逻辑总结了一下Django项目的运行方式和对R ...
- iOS开发项目之一 [ 项目流程]
项目流程 *人员配置 *客户端(iOS工程师,Android工程师) *前端 h5 *后台人员(php,java,net) *提供接口(请求地址.请求参数,请求方式,接口文档) *UI UE * 效果 ...
- ng机器学习视频笔记(十六) ——从图像处理谈机器学习项目流程
ng机器学习视频笔记(十六) --从图像处理谈机器学习项目流程 (转载请附上本文链接--linhxx) 一.概述 这里简单讨论图像处理的机器学习过程,主要讨论的是机器学习的项目流程.采用的业务示例是O ...
随机推荐
- AtCoder AGC002F Leftmost Ball (DP、组合计数)
题目链接: https://atcoder.jp/contests/agc002/tasks/agc002_f 题解: 讲一下官方题解的做法: 就是求那个图(官方题解里的)的拓扑序个数,设\(dp[i ...
- Java并发编程的艺术笔记(二)——wait/notify机制
一.概述 一个线程修改了一个对象的值,另一个线程感知到变化从而做出相应的操作.前者是生产者,后者是消费者. 等待/通知机制,是指一个线程A调用了对象O的wait()方法进入等待状态,而另一个线程B调用 ...
- 基于thinkphp开发的项目部署到由宝塔面板创建的LNMP服务器上解决路径出错问题
一. 环境与版本: 主机:amazon aws EC2主机 系统:Ubuntu 18.04.2 LTS (GNU/Linux 4.15.0-1039-aws x86_64) 面板:宝塔免费版 6.9. ...
- eclipse 简单配置
1.安装STS4 help-->Eclipse Maketplace-->search 'STS'-->install 2.代码提示 Window-->preferences- ...
- Oracle JET Router 与 Module 数据传递
Oracle JET 组件间数据传递方法. 路由:父路由:customers Router 子路由: cust Router 这里 Router 和 module 结合使用. customer 包括 ...
- squid的处理request和reply的流程
request处理: Breakpoint , SQUID_MD5Final ( digest= { (gdb) bt # SQUID_MD5Final ( digest= # ) at store_ ...
- 在WCF程序中动态修改app.config配置文件
今天在个WCF程序中加入了修改配置文件的功能.我是直接通过IO操作修改的app.config文件内容,修改后发现发现其并不生效,用Google搜了一下,在园子里的文章动态修改App.Config 和w ...
- springboot打war包部署tomcat服务器,以及表单提交数据乱码处理
小白觉得springboot打成jar包直接使用内嵌的tomcat或jetty容器(java -jar xxx.jar)运行项目不利于定位问题,我还是习惯于查看tomcat或nginx的日志来定位问题 ...
- c++ 加载资源文件
int _tmain(int argc, _TCHAR* argv[]) { HRSRC hRsrc = FindResource(NULL, MAKEINTRESOURCE(IDR_DATA1), ...
- mysql 锁超时
对一个别人正在读写的表执行DDL操作,经常需要先锁表,但是这个表正在被人执行读写操作,那么就会报:Lock wait timeout 类的错误. 通过MDB实例详情页面的进程管理可以看到类似如下的情况 ...