django 与react结合_django可以跟react结合吗 - CSDN
精华内容
参与话题
  • 网上关于如何解决Django的跨域问题的文章有很多; 一般来说,参考django解决跨域请求的问题 - AFei0018-博客 - CSDN博客这篇文章...以使用React为例,如果是用ajax发请求,可以参考这篇Django配置Ajax跨域调用/设置...

    网上关于如何解决Django的跨域问题的文章有很多;
    一般来说,参考django解决跨域请求的问题 - AFei0018-博客 - CSDN博客这篇文章,装一下django-cors-headers,settings.py里设置一下中间件即可解决。
    但当和前端结合在一起工作时,解决跨域还需要前端的协助。以使用React为例,如果是用ajax发请求,可以参考这篇Django配置Ajax跨域调用/设置Cookie - 孔天逸’Blog - CSDN博客
    但仅仅设置后端是不够的。当前后端通信时仍然会遇到cookie为空的情况。
    我的开发场景为React+axios,通过搜索了解到为了解决cookie的问题,使用axios时,要在import axios的时候,设置withCredentials参数为true(aixos默认为false),即:

    axios.defaults.withCredentials=true;
    
    

    这样前端才能正常地发送cookie到后端。

    但到这一步,虽然cookie可以被后端正常收到,但是Django自带的session却始终为空。
    我们知道session的实现是依赖于cookie的, 简单来说,session的数据存储在服务器(如Django链接的数据库)中,服务器通过cookie将session id传到前端,前端再向请求后端发请求时会同时发回session id,这样经过Django的中间件的处理,我们可以方便地在view中使用session作权限管理等。但是在本场景下,当前端服务器和后端服务器不在同一主机(ip)时,session中的内容始终无法正常地被后端访问到,session始终为空。我搜遍了各种解决方法,几乎遍历式地尝试了各种设置,始终不能成功。经过手动在cookie中设置“sessionid”字段,发现原因应该为Django的中间件会直接过滤掉该字段,从而导致客户端无法保存sessionid,进而在之后客户端向服务端发送url请求时,无法把正确的sessionid发给服务端,自然Django的中间件也无法获得对应的session数据了。
    而过滤的原因是因为Django的SESSION_COOKIE_DOMAIN字段限制了session的cookie的作用域,使得session id只能局限于服务器本地网中,我们可以通过改变这个参数来改变作用域,但Django的这个参数只能指定一个域名。为了以后拓展的方便,我手动在cookie中添加了一个"session_id"参数,手动指定的参数可以被传递给各个网址。然后前端再从response中提取这个参数,保存到前端的cookie中,这样后端就可以正常访问cookie,从而可以正常从数据库中取出对应的session。

    前端代码示例:

    import axios from 'axios'
    import {LOGIN_EVENT, FETCH_RECS, SET_FAVORITES} from './types'
    
    // axios.defaults.xsrfCookieName = "csrftoken";
    // axios.defaults.xsrfHeaderName = "X-CSRFToken";
    axios.defaults.withCredentials=true;
    
    
    function setCookie(name,value) {
        var days = 14;
        var exp = new Date();
        exp.setTime(exp.getTime() + days*24*60*60*1000);
        document.cookie = name + "="+ escape (value) + ";expires=" + exp.toGMTString()+"; path=/";
    }
    export function loginAction(data){
      return function(dispatch){
        axios.post('http://xxx.xxx.xxx.xxx/login/',{
            username:document.getElementById('username').value,
            password:document.getElementById('password').value,
            login_time:Date.now()
          }).then(res => {
            if(res.data.status==="success"){
              setCookie("sessionid", res.data.session_id)
              let userInfo = res.data.data
            }
          else{
            alert('登录出现错误');
          }
        }).catch(e=> {
          alert('登录出现错误(' + e + ')')
        })
      }
    }
    
    

    后端代码示例:
    添加session key到cookie中:

    session_id =request.session.session_key
                print('session id in login request: '+str(session_id))
                ....
                ## 注意下面是response 不是request;客户端浏览器能从cookie中读到我们的session_id
                response.set_cookie('session_id',session_id)
    

    使用session key 读取数据库中的session:

    from django.contrib.sessions.models import Session
    
    ...
    
    
    session_id =request.COOKIES['session_id']
            print("sid in request in feeds:"+str(request.COOKIES['session_id']))
            sess = Session.objects.get(pk=session_id)
            sess_data = sess.get_decoded() #sess_data是一个字典
    

    前后花了整整一天,被这种前后端结合的bug折磨得有点惨,最后算是搞清楚了cookie和session的发送与存储方式,事实证明在解决复杂bug时,如果搜不到类似案例,还是读源码最有效。

    另外还要感谢这几篇文章的作者!
    django中的session实现 - 知乎
    前后端分离实践(django + vue) · ckdk’s blog

    展开全文
  • 平时上班大家都知道没时间干别的,乘着这两天周末,决定把之前搭好的开发环境,给弄到线上去,其实开发环境也搞了一两天,因为django的csrf的坑,还有就是因为前后端要分离吗,还要搭建前端开发环境。前端是webapck ...

    背景

    因为之前一直在捣鼓Python,本人是前端菜鸟一枚~,一直想着做个小demo,把后端和前端给统一跑起来,正好也可以把掌握的知识梳理一遍,这样前端后端就能够打通,岂不快哉!平时上班大家都知道没时间干别的,乘着这两天周末,决定把之前搭好的开发环境,给弄到线上去,其实开发环境也搞了一两天,因为django的csrf的坑,还有就是因为前后端要分离吗,还要搭建前端开发环境。前端是webapck + react + react-router + mobx + axios + antd,后端是django + mysql + uwsgi + nginx,这是我第一次部署,所以踩了很多坑,包括阿里云也是第一次使用,希望给别的小伙伴一个参考,要是能在这边文章中解决问题,那就开心了,废话不多说,开始正题。

    环境准备

    首先你要有一台线上服务器,先配好服务端的环境,我用的是阿里云的ECS服务器,Linux Ubuntu16.04版本。系统不一样可能下面需要安装的软件依赖也会不同,不过大同小异。不是什么大不了的。登录阿里云控制台,找到服务器实例

    点击远程链接,然后会跳到远程链接页面,页面会有一个弹框,输入远程链接密码,这个密码要记下来,后面登录时会一直使用。登录后的界面

    强烈建议不要使用这个终端,因为太坑,你只能通过clear命令清屏,不能上下翻屏,也不能回滚。。。建议使用ssh命令在本地远程登录: ssh 用户名@ip地址 用户名是你服务器上的用户名,ip地址是你服务器上的公网ip,新买来的服务器默认只有root用户名(第一次使用一脸懵逼,就在想这TM用户名是啥我怎么驾驭它。。笨的要死),建议不要用root账户操作,useradd 用户名 新建一个用户名,然后添加sudo权限,这个很重要哦,不然很多命令没有权限,关于Ubuntu命令自行百度啦。为服务器添加安全组,后面项目会用到端口号,添加22、3306、8080等,用到什么端口加添加什么端口,这里也是一颗坑,不然项目根本无法访问。

    • 安装依赖 当添加好新的账户后,后面所有的操作都将在这个账户下操作了。安装nginx sudo apt-get install nginx这是我用的版本。可能会有别的提示,这是因为需要更新镜像,sudo apt-get update然后在下载应该就可以了,nginx用于与uwsgi配合做请求转发。下载好的nginx的默认路径在 /etc/nginx 这个目录,网上有人说在/usr/local/nginx,这个看具体的环境吧,我觉得这种情况可能是因为安装的方式不同造成的,我是直接install的,网上有的是下载.tar压缩包然后在解压,这样可能就会造成nginx的安装路径不同。

    • 然后启动nginx sudo service nginx start 在浏览器中输入ip地址,如果显示wenlcome....证明nginx正常。如果nginx没有效果,使用此命令systemctl status nginx.service,可以查看具体报错信息。接着安装mysql,sudo apt-get install mysql-server 启动服务sudo service mysql start 查看进程ps ajx|grep mysql 停止服务sudo service mysql stop 重启服务sudo service mysql restart配置mysql进入/etc/mysql/mysql.cnf.d sudo vim mysql.cnf找到bind-address表示服务器绑定的ip,默认为127.0.0.1,把ip地址改为服务器的IP。安装过程中会让你输入密码这个设置下就好,一会用于登录,接着安装mysql客户端sudo apt-get install mysql-client 客户端安装完,就可以登录账户了,通过mysql -uroot -pxxxxxx,默认只有root账户,登陆后添加mysql用户,并设置密码和权限如:grant select on 数据库.表 to 'laowang'@'localhost' identified by '123456';具体自行百度吧,设置好后这是用于django项目在线上操作mysql数据库时要用的用户名和密码等,注意权限的问题,这里也是容易犯错的地方!

    • 安装python虚拟环境,这个虚拟环境很多人开发不一定能用到没有用到的请跳过吧,不过还是建议使用,因为很方便管理维护项目,服务器自带的python版本有2.7和3.5,所以不用安装Python

    sudo pip install virtualenv #安装虚拟环境
    sudo pip install virtualenvwrapper #安装虚拟环境扩展包
    编辑家目录下面的.bashrc文件,添加下面两行。
    export WORKON_HOME=$HOME/.virtualenvs
    source /usr/local/bin/virtualenvwrapper.sh
    使用source .bashrc使其生效一下。
    创建虚拟环境命令:
    	mkvirtualenv 虚拟环境名
    创建python3虚拟环境:
    mkvirtualenv -p python3 name
    
    
    进入虚拟环境工作:
    	workon 虚拟环境名
    查看机器上有多少个虚拟环境:
    	workon 空格 + 两个tab键
    退出虚拟环境:
    	deactivate
    删除虚拟环境:
    	rmvirtualenv 虚拟环境名
    虚拟环境下安装包的命令:
    pip install 包名
    注意:不能使用sudo pip install 包名,这个命令会把包安装到真实的主机环境上而不是安装到虚拟环境中。
    apt-get install 软件
    pip install python包名
    复制代码

    虚拟环境主要是用于隔离项目依赖的版本,多个项目互相不影响

    现在进入你本地开发好的项目根目录,执行pip freeze > list.txt这是导出你这个项目所依赖的全部包,一会要在服务器上的虚拟环境下载这些包,本地通过ssh 命令链接服务器,然后通过scr -r 命令把本地项目上传到服务器,上传前记得把项目的settings.py这个文件配置文件的ALLOWED_HOSTS = ['*',]或者写你的服务器ip, DEBUG = False这个要新建一个文件夹。比如/home/abc/wwwroot/ abc是你服务器当前的账户名,切换到虚拟环境,进入项目然后pip install -r list.txt下载依赖。这个时候你可以通过python3 manage.py runserver 跑起你的项目,看是否正常,如果一切正常,说明环境什么的都是OK的,中间如果有什么不对,缺什么下载什么.

    • 接着安装uwsgi,切换虚拟环境,pip install uwsgi,在这个过程中可能会出错,这是因为系统缺少依赖,另外就是所用的python版本造成的,我用的是3.5的版本,然而系统好像默认是2.7。比如这些libpcre3 libpcre3-dev zlib1g-dev openssl libssl-dev python3-dev python-dev,缺什么下载什么,可以通过dpkg -l | grep zlib这个命令查看系统是否有对应的依赖,然后通过sudo apt-get install 下载。 进入项目根目录,sudo vim uwsgi.ini 文件叫什么名字无所谓,然后加上下面内容
    [uwsgi]
    #使用nginx连接时使用
    #socket=127.0.0.1:8080
    #直接做web服务器使用
    http=127.0.0.1:8080
    #项目目录
    chdir=xxxxxxx
    #项目中wsgi.py文件的目录,相对于项目目录
    wsgi-file=xxxxxx
    processes=4
    threads=2
    master=True
    pidfile=uwsgi.pid
    daemonize=uwsgi.log
    #virtualenv=xxxxx
    
    
    复制代码

    这是我的配置,可以看到下面有一个home和virtualenv配置它们的路径是一样的,效果却不一样如果我用virtualenv它就跑不起来,用home就可以,这个坑踩了好长时间。。。都是泪,它们视乎都是用户虚拟环境的配置,有空在查下资料它们的区别。

    进行到这一步,上面我用的是socket的链接,这是和nginx配合使用的,这个不急一会再说,现在先把socket注释掉,把http打开,后面的端口号根据自己项目来定。然后保存退出编辑,通过命令,此时所在的目录是项目根目录,uwsgi --ini uwsgi.ini 启动uwsgi服务,这个时候就不用python3 manage.py runserver了,uwsgi就可以充当web服务器,这样是检验当前的配置依赖,一切是否都正常,启动后,可以在浏览器中输入IP地址加端口号以及你配置的urls的路径,看是否返回正常,注意这个时候是测试,所有请用get请求,不要用post 因为post有csrf的问题。或者直接在命令行中输入python3,进入python执行环境,import requests 然后requests.get('127.0.0.1:8888/xxxx')查看返回状态。若是ok那么到目前一切正常,如果有错误 请查看项目根目录下面生成的uwsgi.log日志文件,查看日志文件,是解决问题的最好办法。如果没问题,就把socket打开,http注释掉,下面要把nginx和uwsgi结合起来。

    • 再次之前把通过webapck打包好的前端dist文件夹上传到服务器,位置应该没有影响,我放在nginx的目录下面了。找到nginx目录,/etc/nginx/nginx.conf:
    	server {
    		listen       80;
    		server_name  localhost;
    
    		#charset koi8-r;
    
    		#access_log  logs/host.access.log  main;
    
    		#location / {
    		#    root   html;
    		#    index  index.html index.htm;
    		#}
    	        # root  /etc/nginx/dist; 		
    	       location / { 
    			
    		           add_header 'Access-Control-Allow-Origin' '*'; 
                               add_header 'Access-Control-Allow-Credentials' 'true';
                               add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
                               add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
                               root  /etc/nginx/dist;      #"这里就要指定你的前端目录文件了,也就是刚刚放进nginx根目录的文件夹"
                               index html index.html;     #"build 目录下默认有index.html 指定默认文件"
                               try_files $uri /index.html;   #"这块分重要,曾经不加尝试过,当我访问login路径时,他不会自动跳转,具体自行百度"
    	                   #error_page 405 =200 $uri; 
    		}
                   location  ~ /api/* {#这个是前端ajxa的请求地址,比如33.66.0.1:8888/api/register,都会转发给django后端,这个和开发环境还是有区别的,前端可以通过webpack的devserver做转发,所有后端的地址在上线时,要注意和这个设置的路由要匹配
                               include uwsgi_params;
                               uwsgi_pass 127.0.0.1:8888; 
                   }
    	    #这个是你通过webpack打包后的html页面加载的文件路径
    		location /static {
    			# 指定静态文件存放的目录
    			alias /etc/nginx/dist/;	
    		#	root /home/zjp/wwwroot/dist;
    		#        index index.html index.html;
                    #        try_files $uri /index.html;
    		}
    
    		#location = / {
    		#	proxy_pass http://172.16.179.131;	
    		#}
    		#error_page  404              /404.html;
    
    		# redirect server error pages to the static page /50x.html
    		#
    		error_page   500 502 503 504  /50x.html;
    		location = /50x.html {
    		    root   html;
    		}
    
    		# proxy the PHP scripts to Apache listening on 127.0.0.1:80
    		#
    		#location ~ \.php$ {
    		#    proxy_pass   http://127.0.0.1;
    		#}
    
    		# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    		#
    		#location ~ \.php$ {
    		#    root           html;
    		#    fastcgi_pass   127.0.0.1:9000;
    		#    fastcgi_index  index.php;
    		#    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    		#    include        fastcgi_params;
    		#}
    
    		# deny access to .htaccess files, if Apache's document root
    		# concurs with nginx's one
    		#
    		#location ~ /\.ht {
    		#    deny  all;
    		#}
          }
    复制代码

    这里面一个坑就是要把#include /etc/nginx/conf.d/*.conf; #include /etc/nginx/sites-enabled/*;注释掉,因为当访问80端口的时候,会默认把/var/www/html/下的文件给你返回,这样你自己的静态文件就无法显示,这是因为里面有默认的配置。更多nginx的配置自行百度。接下来就是收集django所依赖的静态文件了,因为是前后端分离的项目,所以django所需要的静态文件并不多,需要在服务器上新建一个文件夹,来存放所收集的静态文件,然后记住这个路径,在项目的settings.py的加上:

    STATIC_ROOT = '/var/www/reactObject/static/'
    
    复制代码

    保存,提醒:这时候还要注意mysql的配置,因为现在是线上环境了,所以settings文件中的数据库的账户也要记得修改。然后执行python manage.py collectstatic,就会把文件存放在STATIC_ROOT这个指定的目录下,然后在上面的nginx的目录中配置对应的路由。因为我的这个项目静态文件都在前端,所以我收集的时候,没有文件。也就没有配置对应的路由。

    另外在我配置nginx和uwsgi的时候,我在网上看到一个小伙伴说要把下面红色的文件

    放在项目根目录的下面,我信你个鬼,你这糟老头子坏的很~ 我把它放在了项目目录的下面怎么都跑不起来,又是检查各种配置是否有误,检查log文件等。。。都是泪不说了,后来也看了别人的博客,发现根本没有这个文件,而且这个文件都是默认安装的,不需要动它。

    到了这一步基本配置都差不多结束了。重新启动nginx 和uwsgi。这个时候你在浏览器中输入IP地址加端口号,没问题的话就可以出来页面了。

    如果你有域名的话,可以把域名跟服务器绑定,通过域名解析就可以啦~我的小demo,当我看见页面完完整整出来的时候,心里真是太爽了!这里面其实有很多可以优化的地方,后面再说,先跑通才是最要紧,觉得不错给个赞吧

    展开全文
  • drf-react, 结合 Django Rest框架,使用 web service Django Rest框架 反应在 geezhawk.github.io 找到的教程示例代码。要自己尝试,请克隆 repo 并运行:npm installpip install -r requirements.txtexpo
  • scrapy+selenium+react+django实现页面信息的爬取呈现selenium爬取动态页面scrapy+Django保存表单信息react+Django跨域问题react 本学期接到的第二个学习任务:对某页面进行信息爬取,之后将爬取到的信息展示在...

    scrapy+selenium+react+django实现页面信息的爬取与呈现

    本学期接到的第二个学习任务:对某页面进行信息爬取,之后将爬取到的信息展示在自己的页面上,因为第一个学习任务是基于Django框架的web端人脸识别注册登录界面的编写,而之后的规划想做前端,所以要求本任务使用react+Django框架。作为一个入门的渣渣,就是一个不断百度的过程,此博客就记录一下,各个部分百度的结果,可以指责但请温柔~
    整体的demo
    在这里插入图片描述
    standard_query是Django部分,建立了一个APP:query,然后是前端和爬虫。

    selenium爬取动态页面

    刚开始接到任务的时候觉得先做爬虫部分,之前跑过一个很简单的爬虫代码,查看源代码—找到所需内容—正则表达式—爬取成功。这个任务和之前的区别在于,我要的信息通过js提交表单之后不跳转页面显示table信息,于是,第一次百度开始了,这部分有N多博客详细介绍而我又只是套路,所以只介绍一下我使用的版本【虽然firefox版本也是百度到的】:Firefox55+geckodriver19.1+selenium(我使用的是当前最新版3.141.0)只能说这一套可以用,因为之前百度的时候看Firefox新版不支持刚好百度到了这个版本可以用,其他的自行尝试。
    代码示例:

    from selenium import webdriver
    import json,re
    
    def getHtml(url):
        driver = webdriver.Firefox()
        driver.get(url)
        driver.find_element_by_xpath('//tfoot/tr/td/select/option[last()]').click()
        html = driver.page_source
        driver.quit()
        return (html)
    
    def getInfo(html):
        info_pattern = re.compile(info_href,re.S)
        info = re.findall(info_pattern,html)
        print(info)
    
    if __name__ == '__main__':
        url = 'https://www.tc260.org.cn/front/bzcx/zhcx.html'
        info_href = r'<td.*?>(.*?)</td>'
        html = getHtml(url)
        getInfo(html)
    

    scrapy+Django保存表单信息

    真是一个悲伤的故事,开始成功使用webdriver爬取到table信息之后满心欢喜,但是第二步要保存到Django数据库的时候我又懵逼了o(╥﹏╥)o迄今为止我并未使用过一次数据库语言┓( ´∀` )┏上次的任务是直接将ajax异步POST的表单信息new一个模型之后放进去的,但是这次不行了啊,表单信息不是我用Django form类生成的,again,百度,Djangoitem!基于scrapy框架,其中的item使用Djangoitem,直接调用Django里建立的model就可以,之后保存数据的时候只需在pipelines里item.save()即可。结合selenium动态爬取,代码示例如下。
    spider,这部分主要是处理response,我对返回的数据依旧以n乘4的形式存入数据库,实现方式很是笨拙,又暂时没有想到其他方法,就先这样了。利用正则找数据而不是xpath是因为到300左右的时候会存在某一项为空的情况,使用hxs.select(…/text)返回的list里该项就会没有任何信息,会打乱item%4的规律,用正则返回值为空,可以使用,当判断页面存在下一页时,使用yield再一次发起request,因为我爬取的是不跳转页面只提交表单,所以URL不变,也因此需要关闭指纹,dont_filter = True。

    # -*- coding: utf-8 -*-
    import scrapy,re
    from  scrapy.selector import XmlXPathSelector
    from items import StandardItem
    
    i = 0
    class StandardSpider(scrapy.spiders.Spider):
        name = 'standard'
        allowed_domains = ['tc260.org.cn']
        start_urls = ['https://www.tc260.org.cn/front/bzcx/zhcx.html']
        def parse(self, response):
            hxs = XmlXPathSelector(response)
            if re.match('https://www.tc260.org.cn/front/bzcx/zhcx.html',response.url):
                html = response.body.decode('utf-8')
                info_href = r'<td.*?>(.*?)</td>'
                info_pattern = re.compile(info_href, re.S)
                info = re.findall(info_pattern, html)
                td_list = info[:-1]
                for index,td in enumerate(td_list):
                    while index%4 == 0:
                        item = StandardItem()
                        item['norm_name'] = td_list[index]
                        index += 1
                        if td_list[index].strip() == '':
                            item['norm_type'] = 'xx'
                        else:
                            item['norm_type'] = td_list[index].strip()
                        index += 1
                        if td_list[index] == '':
                            item['norm_admin_name'] = 'xx'
                        else:
                            item['norm_admin_name'] = td_list[index]
                        index += 1
                        item['norm_co_name'] = td_list[index]
                        yield item
    
                next_page = hxs.select('//tfoot/tr/td/a[last()-1]/text()').extract()
                if next_page[0] == '下一页':
                    global i
                    i += 1
                    yield scrapy.Request(url=response.url,callback=self.parse,meta={'i':i},dont_filter=True)
    

    item,调用Django的model

    from scrapy_djangoitem import DjangoItem
    from query.models import Standard
    
    class StandardItem(DjangoItem):
        django_model = Standard
    

    pipelines,这里只需要对数据进行保存,个人认为更进一步的处理应该有爬取信息与数据库现有信息的对比,否则每次运行他会直接添加进去,但是时间有限,就先这样。

    class StandardQuerySplidePipeline(object):
        def process_item(self, item, spider):
            item.save()
            return item
    

    middlewares,这部分是对request进行处理,selenium的作用就是在这,我爬取的内容需要在页面点击提交或者每页内容等才可以在源代码中显现,所以要模拟浏览器驱动。

    from selenium import webdriver
    from scrapy.http import HtmlResponse
    
    class SeleniumMiddleware:
        def process_request(self,request,spider):
            option = webdriver.FirefoxOptions()
            option.add_argument('headless')
            option.add_argument('--user-agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0"')
            option.add_argument('--disable-infobars')
            driver = webdriver.Firefox(firefox_options=option)
            driver.get(request.url)
            driver.find_element_by_xpath('//tfoot/tr/td/select/option[last()]').click()
            i = request.meta.get('i')
            if i == None:
                body = driver.page_source
                driver.quit()
                return HtmlResponse(url=request.url,body=body,request=request,encoding='utf-8',status=200)
            else:
                while i != 0:
                    driver.find_element_by_xpath('//tfoot/tr/td/a[last()-2]').click()
                    i = i-1
                body = driver.page_source
                driver.quit()
                return HtmlResponse(url=request.url, body=body, request=request, encoding='utf-8', status=200)
    

    还好这个数据只有649条,他最多疯狂点击了7次,再大一些就要考虑放弃selenium了(╥╯^╰╥)

    最后可以在main里加一条语句,省的每次打开cmd

    from scrapy import cmdline
    cmdline.execute('scrapy crawl standard --nolog'.split())
    

    react+Django跨域问题

    axios+corsheaders,这一部分真真是完全懵逼脸,百度出结果也完全不懂为什么,反正能用,这一部分的配置建议查看我参考的博客:https://blog.csdn.net/weixin_33912638/article/details/87587514
    具体使用查看我参考的另一篇博客:
    https://blog.csdn.net/u013210620/article/details/79917198
    感觉写的很好,毕竟让我这个小白成功的进行了数据的交互。
    react部分的配置,axios发起请求,baseURL是Django的默认地址。

    axios.defaults.withCredentials = true;
    axios.defaults.headers.post['Content-Type'] = 'application/json';
    axios.defaults.baseURL = 'http://127.0.0.1:8000';
    

    调用的时候:

    await axios.get('/query/',{params:param})
        .then(response => {console.log(response.data);
          this.getDataRead(response);
        })
        .catch(error => console.log(error))
    

    成功/失败之后的操作随意一些,我懒得改直接粘了我的源码,嗯,源码也很随意
    前端调用,后端就要有相应的URL。
    项目下的urls文件:

    from django.contrib import admin
    from django.urls import re_path,include
    
    urlpatterns = [
        re_path('admin/', admin.site.urls),
        re_path(r'query/',include('query.urls')),
    ]
    

    APP下的urls文件:

    from django.urls import re_path
    from . import views
    
    urlpatterns = [
        re_path(r'^$',views.query),
    ]
    

    处理URL的request时,返回obj,添加Access-Control-Allow-Origin

    from django.http import HttpResponse
    from .models import Standard
    import json
    def query(request):
        params = request.GET.get('name')
        standard_list = Standard.objects.filter(norm_name__contains=params) | Standard.objects.filter(norm_type__contains=params) | Standard.objects.filter(norm_admin_name__contains=params) | Standard.objects.filter(norm_co_name__contains=params)
        queryout_list = []
        for index,standard in enumerate(standard_list):
            #queryout_list.append({'项目名称':standard.norm_name,'项目类型':standard.norm_type,'主要研制人':standard.norm_admin_name,'承担单位':standard.norm_co_name})
            queryout_list.append([standard.norm_name,standard.norm_type,standard.norm_admin_name,standard.norm_co_name])
        queryout = json.dumps(queryout_list)
        obj = HttpResponse(queryout)
        obj['Access-Control-Allow-Origin'] = 'http://localhost:3000'
        return obj
    

    为了使后端接收到request,需要corsheaders,这个在Django的settings文件里进行配置,这个CORS_ORIGIN_WHITELIST就是react默认的地址

    CORS_ALLOW_CREDENTIALS = True
    CORS_ORIGIN_WHITELIST = ('loaclhost:3000')
    
    CORS_ALLOW_METHODS = (
        'DELETE',
        'GET',
        'OPTIONS',
        'PATCH',
        'POST',
        'PUT',
    )
    
    CORS_ALLOW_HEADERS = (
        'accept',
        'accept-encoding',
        'authorization',
        'content-type',
        'dnt',
        'origin',
        'user-agent',
        'x-csrftoken',
        'x-requested-with',
    )
    

    然后把他加入到APP中:

    INSTALLED_APPS = [
        'query',
        'corsheaders', #跨域问题的解决
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
    

    还有middleware,这有一个顺序问题,就是cors要放到common前边。

    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'corsheaders.middleware.CorsMiddleware',
        'django.middleware.common.CommonMiddleware',
        #'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]
    

    react

    前端这一块是我接下来要学习的部分,我就写了一个input框,一个button点击搜索,加一个用来展示结果的初步假设是table但最后不算table的table,也没什么好说的,。这里要说的就是一点,我第一次使用的时候,npm start成功打开了网页,后边也成功了两次,但是在这个项目里,我新建之后并没能启动,这个卡了我一天,最后发现是react没在环境变量里,emmm不知道是什么时候安装或者卸载或者怎么的不在了,反正就在环境变量里填上之后就可以了,报错的截图
    在这里插入图片描述
    在这里插入图片描述
    上代码:

    import React,{Component} from 'react';
    import json from 'json3';
    import axios from 'axios';
    //发起请求
    import './Query.css';
    
    axios.defaults.withCredentials = true;
    axios.defaults.headers.post['Content-Type'] = 'application/json';
    axios.defaults.baseURL = 'http://127.0.0.1:8000';
    //const server = 'http://127.0.0.1:8000';
    
    
    class Query extends Component {
      constructor(props) {
        super(props);
        this.state = {
          array:[],
          inputValue:''
        }
        this.handelInputChange = this.handelInputChange.bind(this);
        this.handelBtnClick = this.handelBtnClick.bind(this);
      }
    
      handelInputChange(e) {
        this.setState(
        {
          inputValue:e.target.value
        })
      }
    
      getDataRead(response) {
        var len = response.data.length
        for(var i=0;i<len;i++){
          this.setState(
          {
            array:[...this.state.array,response.data[i]]
          });
        }
      }
    
      getDataWrite(response) {
        return (
          this.state.array.map((item,index) =>
          {
            return(
              <tr key = {index}>
                <td id = 'fr'>{this.state.array[index][0]}</td>
                <td id = 'se'>{this.state.array[index][1]}</td>
                <td id = 'thi'>{this.state.array[index][2]}</td>
                <td id = 'fou'>{this.state.array[index][3]}</td>
              </tr>
            )
          })
        )
      }
    
      async handelBtnClick() {
        let param = {
          'name':this.state.inputValue
        }
        this.state.array.length = 0
        await axios.get('/query/',{params:param})
        .then(response => {console.log(response.data);
          this.getDataRead(response);
        })
        .catch(error => console.log(error))
      }
    
      render() {
        return(
          <div>
            <input value = {this.state.inputValue} onChange = {this.handelInputChange}/>
            <button onClick = {this.handelBtnClick}>搜索</button>
            <table>
              <thead>
                <tr className = 'table_com_bg'>
                  <th id = 'frti'>项目名称</th>
                  <th id = 'seti'>项目类型</th>
                  <th id = 'thiti'>主要研制人</th>
                  <th id = 'fouti'>承担单位</th>
                </tr>
              </thead>
              <tbody>
                {this.getDataWrite()}
              </tbody>
            </table> 
          </div>
        );
      }
    }
    
    export default Query;
    

    基本就是这些,纪念一下我的第二个学习任务,感觉还有很多需要完善的地方,比如爬取到的信息添加到数据库时item的筛选,是否需要定时爬取,代替selenium的工具,前端的css编写,balabala,我先学习别的了,挥手┏(^0^)┛

    展开全文
  • django与react结合

    千次阅读 2018-05-05 20:57:37
    初学react,在学完基本的语法之后,想要做一个基本的小demo出来,首先分别建好一个python的项目,我使用的框架为django,然后再创建好一个react的项目,接下来就是django与react结合了(嗯,困扰了我一天多的问题)...

    初学react,在学完基本的语法之后,想要做一个基本的小demo出来,首先分别建好一个python的项目,我使用的框架为django,然后再创建好一个react的项目,接下来就是django与react的结合了(嗯,困扰了我一天多的问题)。

    首先,将react项目进行编译打包(由于我创建react项目用的是create-react-app,所以直接运行npm run start就可以了),完成后会生成一个build文件,然后将build文件夹里的文件(除static文件夹)全部app下的templates文件夹下,static文件夹里的内容放到app下的static文件夹里(此时build文件夹可以让它彻底消失了),然后将react项目里的其他的文件可以放在app下的某个文件夹里了,这是就可以运行python manage.py runserver这个命令了(python项目的一些基本配置例如:urls, settings等等提前都要配置好哦),ok , 结束。

    项目文件的目录结构;


    frontend详情:


    展开全文
  • django中使用react项目

    千次阅读 2018-02-11 16:36:27
    django准备工作1.创建一个django项目2. 安装djangorestframework,并将其注册到settings.py的INSTALLED_APPS里 pip install djangorestframework3. 解决跨域访问的问题,django-cors-middleware能够为我们解决此...
  • 在尝试把Django作为一个单纯的REST框架配合React进行web开发的时候遇到了使用axios发出post请求,但Django后端收不到数据的情况。 axios代码是很普通的样例代码: axios({ method: 'post', url: '/api/../...
  • PyCharm+python3+django+vue 开发环境搭建

    千次阅读 2019-06-05 16:40:48
    一:版本 1: 请自行安装Pycharm + Python3 1>pycharm 官方文件下载地址,请根据自己的电脑自行选择对应的软件下载 点击进入pycharm官方下载 pycharm激活码(PS:可以在里面找到所有... 2>...安装项目虚拟环境...
  • 本篇课程结合前面学习的Angular6和Django框架,将两个框架通过一个实战项目结合在一起,用目前流行的前后端分离开发模式,从零起步,一步步开发成为一个完整的项目并最终打包发布。视频中所出现的细节,错误,以及...
  • Koa+React+Webpack环境配置 1. 初衷 最近,因疫情在家写了一些东西.想到之前去实习的时候,公司用的Nodejs做中间层,实现数据格式的处理,请求转发,SSR等功能,想自己也折腾下这么个东西,刚好最近或多或少的学了...
  • 在有Django表单输入的页面中,就很难将两者很好的结合起来。自己在学习新版的Angular时,跟了2遍官方网站的“英雄指南”教程。第1次完全是照搬,熟悉了一下基本概念;第2次自己做了一些修改,写了一个图片分享...
  • 原视频:Assets in Django without losing your hair - PyCon 2019 Django 处理静态资源相对而言是比较蛋疼的,该 talk 作者给我们介绍了 django app 处理静态资源的四个发展阶段(或者说场景),从最简单的单机文件...
  • Python 使用 Django 框架,进行 web 开发,一点都不比目前 JavaEE 最简便的框架 SpringBoot 差,甚至是更加便捷。 ① 使用 python manage.py makemigrations、python manage.py migrate,即可实现 JavaEE 方面的 ...
  • react和vueAs for React and Vue.js, there’s enough said about them on the net. Svelte is a relatively young framework, so we’ll just add a couple of words about it. The most striking difference from ...
  • 用最快的速度领略一下 ...ReactDjango 怎么实现前后端分离的开发,有好的教程、博客推荐吗? 现在用 React 写单一的小组件,怎么结合到页面应用里? 当前内容版权归码字科技所有并授权显示,盗版必究。阅读原文
  • 让我们看一下如何在不等待外部REST服务的情况下调用它们,并独立进行多个并行调用,然后将其结果Java EE 8中的响应管道结合起来。 如果我们的服务调用了多个微服务,并等待每个调用完成并返回结果,然后再执行...
  • 作者 Dan Abramov,Redux作者,React Core Team成员转载并翻译自Dan的博客,已获得Dan授权10年前,我还是一个大一新生。那年我17,没有工作,没有圈子,还...
  • 超小团队选择django还是flask? 题主的情况是这样 ,题主是一名大学生,想帮自己的社团写一个主页app承载社团申请,社团blog,社团信息服务,留言板等功能, 题主的技术情况是前后端都懂一点,前端是使用...
1 2 3 4 5 ... 20
收藏数 612
精华内容 244
关键字:

django 与react结合