继承代码阅读与注释
一、Django部分(Journal / User)
-
journal(仅以下提到的py文件有用,其他都不用管)
-
models.py + serializers.py: (模型+序列化方法,序列化产生json
- 用户IP记录 UserIp(ip=char,count=int) 对应序列化,id,ip,count
- 访问数 VisitCount (count=int) 对应序列化,id,count
- 日期记录 DayCount(day=date,count=int) 对应序列化,id,date,coun
-
urls.py
- 访问localhost:8000/api/journal/visit/ 调用views.Visit
- 访问localhost:8000/api/journal/statistics/ 调用views.Statistics
-
views.py
-
Visit
只有一个POST方法, count 置为 VisitCount对象的数量 #这句没用到,不知道为什么在这,对应代码如下,后续一致,不再赘述。 count = VisitCount.objects.all() 根据request.META获取HTTP报文的IP,若同一IP则该UserIp的count+1, 否则新建一个UserIp,其count赋值为1 if 'HTTP_X_FORWARDED_FOR' in request.META: client_ip = request.META['HTTP_X_FORWARDED_FOR'] client_ip = client_ip.split(",")[0] else: client_ip = request.META['REMOTE_ADDR'] exist = UserIp.objects.filter(ip=str(client_ip)) if exist: uip = exist[0] uip.count += 1 else: uip = UserIp() uip.ip = client_ip uip.count = 1 uip.save() 根据当前日期找出对应的日期记录,找到则对应count+1,否则新建一个DayCount对象,date置为现在的时间,count记为1 date = timezone.now().date() today = DayCount.objects.filter(day=date) if today: day_record = today[0] day_record.count += 1 else: day_record = DayCount() day_record.dayTime = date day_record.count = 1 day_record.save() 返回HTTP201(成功)
-
Statistics
只有一个Get方法, data = { "visit_count": vist_count['count__sum'], #返回各IP访问量之和 "date_count_list": date_count_list_serializer.data, #所有DayCount的json "network_api_count": network_api_count, #网络数目 "user_count":user_count #用户数目 } #实际数据例子如下 { "visit_count": 12, "date_count_list": [ { "id": 1, "day": "2020-04-06", "count": 12 } ], "network_api_count": 1, "user_count": 2 }
-
-
-
user
-
models.py + serializers.py:
-
test.py
一组用户注册测试数据,
python manage.py test user/
可自动化测试。 -
urls.py
urlpatterns = [ url(r'^register/$', views.UserRegister.as_view()), url(r'^login/$',obtain_jwt_token), url(r'^info/$',views.UserInfo.as_view()) ] 分别是 访问localhost:8000/api/user/register/ 调用views.UserRegistor 访问localhost:8000/api/user/login/ 调用obtain_jwt_token,验证相关,他们掉包做好了,其实可以不用管这部分 访问localhost:8000/api/user/ingo/ 调用views.UserInfo
-
utils.py
用户认证相关的设置,也可以不管
-
views.py
-
UserRegistor
只有一个POST方法,用于新建用户 def post(self, request): serializer = UserSerializer(data=request.data)#json->对象 if serializer.is_valid():#数据有效则建立 serializer.save()#保存用户对象 # 注册时签发一个token来自动登录 payload = jwt_payload_handler(serializer.instance) token = jwt_encode_handler(payload) res = serializer.data res["token"] = token return Response(res, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)#无效则返回HTTP400
-
UserInfo
只有Get方法, 返回用户数据Json 例子如下 { "id": 1, "password": "pbkdf2_sha256$120000$gCiyqC4gkN1k$/IVeCbd5gsu2T5RMNRpO50MxeC9vx14diuKXgSGDx9A=", "username": "pandapan", "email": "1009303269@qq.com", "is_active": true, "is_staff": true }
-
-
二、前端部分
见 关键前端代码注释
三、后端部分
permission.py,定义的是用户对于模型操作的权限:
from NeuralNetwork.models import Network
class ChangeModel(object):
def has_permission(self, request,view):
aquire_object = Network.objects.get(pk=view.kwargs['pk'])
if request.method == 'GET' or request.user.id == aquire_object.creator_id:
return True
else:
return False
#如果Network所有者和请求访问者id相同或者为get请求,返回true,否则为false
model.py:
class Network(models.Model):
creator = models.ForeignKey('user.User',on_delete=models.CASCADE,null=True)
structure = models.TextField()
name = models.TextField(null=True)
time = models.DateTimeField(auto_now=True)
network共有4个属性,创建者ID,模型名称,创建时间和structure。其中struture为json型文本,记录了network的完整结构。
serializers.py,将network序列化,比较常规
views.py,重要文件,定义了一系列的交互操作
class NetworkList(APIView):
permission_classes = (permissions.IsAuthenticated,)
#允许身份验证通过的用户访问
```
def get(self, request):
user_id = request.GET['id']
if user_id is None:
return Response("need user id", status=status.HTTP_400_NOT_FOUND)
network_list = Network.objects.filter(creator=user_id).values('id', 'time', 'creator_id', 'name')
return Response(list(network_list), status=status.HTTP_200_OK)
#返回登录用户创建的所有Network信息表,不包括structure结构,而是一张统计表
def post(self, request):
creator = request.user.id
data = {
"name": request.data["name"],
"creator": creator,
"structure": json.dumps(request.data["structure"])
}
serializer = NetworkSerializer(data=data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
```
#储存用户所创建的Network
class NetworkDetail(APIView):
permission_classes = (ChangeModel,)
#在permission.py中定义,要求用户ID与network ID相同
```
def get_object(self, pk):
try:
return Network.objects.get(pk=pk)
except Network.DoesNotExist:
raise Http404
#获取ID为pk的Network
def get(self, request, pk):
net = self.get_object(pk)
serializer = NetworkSerializer(net)
return Response(serializer.data)
#获取ID为pk的Network,并将其序列化,返回给用户
def put(self, request, pk):
net = self.get_object(pk)
data = {
"name": request.data["name"],
"structure": json.dumps(request.data["structure"])
}
serializer = NetworkSerializer(net, data=data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
#更新id=pk的network
def delete(self, request, pk):
net = self.get_object(pk)
net.delete()
return Response(status=status.HTTP_200_OK)
#删除id为pk的Network
```
@api_view(['POST'])
def gen_code(request):
result = {}
try:
result["Main"], result["Model"], result["Ops"] = ops.main_func(request.data)
#调用translate/ops.py中的main_func生成完整代码,并返回给客户端
except Exception as e:
return Response({str(e)}, status=status.HTTP_400_BAD_REQUEST)
else:
return Response(result, status=status.HTTP_200_OK)
#todo:虽然看起来没啥问题但是问题绝对很大,两个请求同时处理绝对会挂掉!!!!!!!
@api_view(['POST'])
def download_project(request):
data = request.data
write_file(data)
zipf = zipfile.ZipFile("project_VisualPytorch.zip", 'w',zipfile.ZIP_DEFLATED)
#创建一个压缩文件对象
pre_len = len(settings.FILE_DIR)
for parent, dirnames, filenames in os.walk(settings.FILE_DIR):
for filename in filenames:
pathfile = os.path.join(parent, filename)
arcname = pathfile[pre_len:].strip(os.path.sep) # 相对路径
zipf.write(pathfile, arcname)
zipf.close()
#将setting.FILE_DIR(规定的生成文件文件夹)所有的文件添加到压缩包内
```
response = StreamingHttpResponse(file_iterator("project_VisualPytorch.zip"))
response['Content-Type'] = 'application/zip'
response['Content-Disposition'] = 'attachment;filename="project_VisualPytorch.zip"'
#将生成的压缩文件发送给用户,需要注意到的是使用了file_iterator将zip文件变成了字节流传送,原理不明。但直接沿用应该没问题。
return response
```
def file_iterator(file_name, chunk_size=512):
with open(file_name, 'rb') as f:
while True:
c = f.read(chunk_size)
if c:
yield c
else:
break
def write_file(data):
if os.path.exists(os.path.join(settings.FILE_DIR,"project/Main.py")):
os.remove(os.path.join(settings.FILE_DIR,"project/Main.py"))
if os.path.exists(os.path.join(settings.FILE_DIR,"project/Model.py")):
os.remove(os.path.join(settings.FILE_DIR,"project/Model.py"))
if os.path.exists(os.path.join(settings.FILE_DIR,"project/Ops.py")):
os.remove(os.path.join(settings.FILE_DIR,"project/Ops.py"))
if os.path.exists("project_VisualPytorch.zip"):
os.remove("project_VisualPytorch.zip")
#服务器在创建前先删除之前创建的全部相关文件
root_dir = os.path.join(settings.FILE_DIR, "project")
file_main = open(os.path.join(root_dir, "Main.py"), "w")
file_model = open(os.path.join(root_dir, "Model.py"), "w")
file_ops = open(os.path.join(root_dir, "Ops.py"), "w")
file_main.write(data['main'])
file_model.write(data['model'])
file_ops.write(data['ops'])
#将创建的代码全部写入文件中