Django案例 - 音乐网站实现

作者: MA木易YA | 来源:发表于2018-12-04 22:55 被阅读0次

      因为之前的云存储课程,要做一个跟云存储oss相关的案例,因为正好那会儿在学Django,所以首先就想到了用这个来实现一个网站,有想过什么第三方库啊之类的,因为之前有听说过什么七牛云,还有将静态文件压缩保存之类的,之前实验室的上司也曾经有项目涉及到用亚马逊云保存资源的案例,所以就有了我们现在的这个项目,主要是用Django实现一个音乐网站,就不涉及到数据库和模型之类的了,充其量只有用户模块会稍稍涉及一点模型,不过数据很小,占用资源也不多,之后会想其它方法来解决
      前端页面主要是用HTML+js来实现,歌词、歌单也是从js文件里面直接获取,主要就是用Django实现数据传递和动态加载

    文件结构

      直接用tree生成的,没有略去无关文件,主要是让大家简单了解下所用到的模块和文件结构

    卷 F 的文件夹 PATH 列表
    卷序列号为 0F02-10B8
    F:.
    │  db.sqlite3
    │  manage.py
    │  settings.py
    │  tree.txt
    │  urls.py
    │  wsgi.py
    │  __init__.py
    │  
    ├─.idea
    │      dataSources.local.xml
    │      dataSources.xml
    │      misc.xml
    │      modules.xml
    │      oss_test1.iml
    │      workspace.xml
    │      
    ├─file
    │  │  admin.py
    │  │  apps.py
    │  │  models.py
    │  │  test2.py
    │  │  tests.py
    │  │  urls.py
    │  │  views.py
    │  │  __init__.py
    │  │  
    │  ├─migrations
    │  │  │  __init__.py
    │  │  │  
    │  │  └─__pycache__
    │  │          __init__.cpython-36.pyc
    │  │          
    │  ├─templatetags
    │  │  │  url_tag.py
    │  │  │  __init__.py
    │  │  │  
    │  │  └─__pycache__
    │  │          url_tag.cpython-36.pyc
    │  │          __init__.cpython-36.pyc
    │  │          
    │  └─__pycache__
    │          admin.cpython-36.pyc
    │          models.cpython-36.pyc
    │          urls.cpython-36.pyc
    │          views.cpython-36.pyc
    │          __init__.cpython-36.pyc
    │          
    ├─media
    │  └─upload
    │      └─2018
    │          └─02
    │              └─05
    │                      lwpbrq.png
    │                      
    ├─oss_test1
    │  │  settings.py
    │  │  urls.py
    │  │  wsgi.py
    │  │  __init__.py
    │  │  
    │  └─__pycache__
    │          settings.cpython-36.pyc
    │          urls.cpython-36.pyc
    │          wsgi.cpython-36.pyc
    │          __init__.cpython-36.pyc
    │          
    ├─search
    │  │  admin.py
    │  │  apps.py
    │  │  models.py
    │  │  tests.py
    │  │  urls.py
    │  │  views.py
    │  │  __init__.py
    │  │  
    │  ├─migrations
    │  │  │  __init__.py
    │  │  │  
    │  │  └─__pycache__
    │  │          __init__.cpython-36.pyc
    │  │          
    │  └─__pycache__
    │          admin.cpython-36.pyc
    │          models.cpython-36.pyc
    │          urls.cpython-36.pyc
    │          views.cpython-36.pyc
    │          __init__.cpython-36.pyc
    │          
    ├─static
    │  │  base.css
    │  │  home.css
    │  │  jquery-1.12.4.min.js
    │  │  
    │  ├─bootstrap-3.3.7
    │  │  ├─css
    │  │  │      bootstrap.min.css
    │  │  │      bootstrap.min.css.map
    │  │  │      
    │  │  ├─fonts
    │  │  │      glyphicons-halflings-regular.eot
    │  │  │      glyphicons-halflings-regular.svg
    │  │  │      glyphicons-halflings-regular.ttf
    │  │  │      glyphicons-halflings-regular.woff
    │  │  │      glyphicons-halflings-regular.woff2
    │  │  │      
    │  │  └─js
    │  │          bootstrap.min.js
    │  │          
    │  ├─cloud
    │  │      黄耀明 - 暗涌(Live) - live.mp3
    │  │      
    │  ├─css
    │  │  │  base.css
    │  │  │  bootstrap.css.map
    │  │  │  bootstrap.min.css
    │  │  │  bootstrap.min.css.map
    │  │  │  bulma.min.css
    │  │  │  index.css
    │  │  │  music.css
    │  │  │  
    │  │  └─img
    │  │          1.jpg
    │  │          alin.jpg
    │  │          disk.png
    │  │          dknz.jpg
    │  │          hym.jpg
    │  │          js.jpg
    │  │          lf.jpg
    │  │          lkq.jpg
    │  │          lry.jpg
    │  │          lzs.jpg
    │  │          play_btn_next.png
    │  │          play_btn_prev.png
    │  │          play_icn_loop.png
    │  │          play_icn_src.png
    │  │          play_rdi_btn_pause.png
    │  │          play_rdi_btn_play.png
    │  │          process_btn.png
    │  │          song_play_icon.png
    │  │          tofirstpage.jpg
    │  │          xg.jpg
    │  │          xuruyun.jpg
    │  │          zhl.jpg
    │  │          zjx.jpg
    │  │          
    │  ├─fonts
    │  │      glyphicons-halflings-regular.eot
    │  │      glyphicons-halflings-regular.svg
    │  │      glyphicons-halflings-regular.ttf
    │  │      glyphicons-halflings-regular.woff
    │  │      glyphicons-halflings-regular.woff2
    │  │      
    │  ├─img
    │  │      alin.jpg
    │  │      disk.png
    │  │      dknz.jpg
    │  │      download.png
    │  │      file.png
    │  │      hym.jpg
    │  │      img.jpg
    │  │      js.jpg
    │  │      lf.jpg
    │  │      lkq.jpg
    │  │      lry.jpg
    │  │      lzs_.jpg
    │  │      play_disc.png
    │  │      play_needle.png
    │  │      search.png
    │  │      timg.jpg
    │  │      upload.png
    │  │      xg.jpg
    │  │      xuruyun.jpg
    │  │      zhl.jpg
    │  │      zjx.jpg
    │  │      
    │  ├─js
    │  │      index.js
    │  │      jquery-min.js
    │  │      lyrics.js
    │  │      move.js
    │  │      music.js
    │  │      
    │  └─media
    ├─templates
    │  │  base.html
    │  │  error.html
    │  │  form.html
    │  │  index.html
    │  │  index2.html
    │  │  
    │  ├─file
    │  │      detail.html
    │  │      list.html
    │  │      search_detail.html
    │  │      search_list.html
    │  │      
    │  └─user
    │          bind_email.html
    │          forgot_password.html
    │          login.html
    │          register.html
    │          user_info.html
    │          
    ├─user
    │  │  admin.py
    │  │  context_processors.py
    │  │  forms.py
    │  │  models.py
    │  │  urls.py
    │  │  views.py
    │  │  __init__.py
    │  │  
    │  ├─migrations
    │  │  │  0001_initial.py
    │  │  │  0002_auto_20181121_1311.py
    │  │  │  __init__.py
    │  │  │  
    │  │  └─__pycache__
    │  │          
    │  │          
    │  └─__pycache__
    │          
    │          
    └─__pycache__
    

    主页

     页面全都是用bootstrap框架做的简单样例,基础(base.html)模板中定义了播放器主页面,上方导航栏定义的是用户模块,包括搜索、上传、下载和用户登录注册模块,如下图(开场动画我就略过了,播放器代码是在github上down的某位大佬的,简单修改了下)


    image.png

      主页主要是是实现了下js数据的传递,播放器本来是从一个专门存储歌词、歌单的js文件里面读取数据,现在我将歌词和歌曲都放在了云服务器的对象存储桶(oss)里面,所以就直接查询数据将它返回到主页,js数据直传详情参考我之前的文章,这里因为我的服务器带宽等一系列条件限制,大量数据处理会反应较慢,这里就只是简单对歌单文件进行了处理,歌词和图片我并没有全部上传(数据太多爆桶要加钱呀QAQ),但是处理方法都是一样的,这里就仅用歌单做个演示,其他数据使用默认,oss的处理也可以参考我前面的内容

    def index(request):
        base_url = "https://maya-music.oss-cn-beijing.aliyuncs.com/"
        files_name = []
        url_list = []
        data = []
        # 打印出云端每个文件的名字,将名字存入files_name列表
        for i in oss2.ObjectIterator(bucket):
            files_name.append(i.key[:-4])
        # 拼接出所有链接,存入url_list字典
        for name in files_name:
            url_list.append(base_url + name + '.mp3')
        for song, src in zip(files_name, url_list):
            data.append({'song': song, 'src': src, 'singer': "黄耀明", 'img': 'static/css/img/hym.jpg', 'lyric': 'anyong'})
        return render(request, 'index.html', {'list': json.dumps(data, ensure_ascii=False)})
    

    上传功能

    在导航栏内添加了bootstrap表单可以实现文件定位,然后Django获取的文件对象,利用自带的文件处理模块,将文件下载至本地,然后用oss模块处理上传至服务器,最后利用chdir、remove等方法将本地文件删除即实现了一个“假上传功能”,只是个用来熟悉Django的小练习嘛不必较真

    def upload_file(request):
        referer = request.META.get('HTTP_REFERER', reverse('home'))
    
        if request.method == "POST":    # 请求方法为POST时,进行处理
            myFile =request.FILES.get("myfile", None)    # 获取上传的文件,如果没有文件,则默认为None
            if not myFile:
                return HttpResponse("no files for upload!")
            destination = open(os.path.join(dir_path, myFile.name), 'wb+')    # 打开特定的文件进行二进制的写操作
            for chunk in myFile.chunks():      # 分块写入文件
                destination.write(chunk)
            destination.close()
            with open(oss2.to_unicode(dir_path+"/"+myFile.name), 'rb') as f:
                bucket.put_object(myFile.name, f)
            temp_path = ".\static"
            os.chdir(os.path.abspath(temp_path))
            shutil.rmtree("media")
            os.mkdir("media")
            os.chdir(now_pwd)
            return redirect(request.GET.get('from', reverse('home')))
    

    下载功能

    原理同上,同样是下载至本地然后实现本地下载,最后删除文件,但是在处理方式上会有些不同,因为没有设计models,所以这里无法定位到具体的歌曲对象,只能实现单首歌曲下载,我的html里面的audio恰好是获取歌单对象,动态实现切换歌曲源,所以audio里面的src恰好就是当前歌曲的url,这里就钻了个空子,直接用requests+BeautufulSoup获取到audio下的src,再将数据转递过去,根据src在远端服务器进行匹配,获取到对应url后进行下载,这里oss无法处理url里面的中文字符,涉及到url转码,可以参考我之前的相应版块的介绍

    def getHTMLText(url):
        try:
            r = requests.get(url, timeout=30)
            r.raise_for_status()#状态码为200则返回文本否则抛出异常
            r.encoding = 'utf-8'
            # r.encoding = r.apparent_encoding
    
            return r.text
        except:
            return "产生异常"
    
    def get_data(html):
        src = BeautifulSoup(html, 'html.parser', from_encoding='utf-8').find('audio', {'id': 'audio'}).get('src')
        return src
    
    
    def download_file(request):
        referer = request.META.get('HTTP_REFERER', reverse('home'))
        url = "http://127.0.0.1:8000/"
        html = getHTMLText(url)
        src = get_data(html)
        file_name = unquote(src, 'utf-8').split('com/')[1]
        temp_path2 = ".\static\cloud"
        os.chdir(os.path.abspath(temp_path2))
        print("***************")
        print("cloud:", os.getcwd())
        bucket.get_object_to_file(file_name, file_name)
        file = open(file_name, 'rb')
        response = FileResponse(file)
        response['Content-Type'] = 'application/octet-stream'
        response['Content-Disposition'] = 'attachment;filename="music.mp3"'
        # file.close()
        # os.remove(file_name)
        os.chdir(now_pwd)
        return response
               # redirect(request.GET.get('from', reverse('home')))
    

    搜索功能

      搜索功能因为没有设计models的原因,也没有办法用自带的搜索模块了(模糊查询),这里就只能自己设计,主要是根据表单内传入的字符串去远端服务器内进行匹配,因为服务器内文件的url是根据名字生成的,会包含文件名,所以可以根据名字进行查询,然后返回结果集,将数据返回到新的展示页面,页面就简单展示了下数据,并没有特殊设计,同样继承自base.html


    image.png
    def get_filesname():
        files_name = []  # 歌曲名字
        for i in oss2.ObjectIterator(bucket):
            files_name.append(i.key[:-4])
        return files_name
    
    def get_picname(list_):
        pic_name = []  # 图片全称
        for name in list_:
            pic_name.append("https://maya-picture.oss-cn-beijing.aliyuncs.com/"+name+".jpg")
        return pic_name
    
    def get_singer(list_):
        singers = []  # 歌手名字
        for name in list_:
            s_name =  name.split(' - ')[0]
            singers.append(s_name)
        return singers
    
    def search(request):
        search_page = request.POST.get('name')
        # search_page = input("请输入")
        search_song = []
        search_singer = []
        context = {}
        files_name = get_filesname()
        for name in files_name:
            if search_page in name:
                search_song.append(name)
        search_singer = get_singer(search_song)
        search_pic = get_picname(search_song)
        context['search_song'] = search_song
        context['search_singer'] = search_singer
        context['search_pic'] = search_pic
        context['result'] = list(zip(search_song, search_singer, search_pic))
        context['src'] = search_song
        for x,y,z in zip(context['search_song'],context['search_singer'],context['search_pic']):
            print("song:%s singer:%s pic:%s" %(x,y,z))
    
        return render(request, 'file/search_list.html', context)
    

    歌曲详情页

      这里本来是除了展示歌曲详情信息,另外还想增加歌单模块、评论模块的,但是依然是苦于models的折磨,就只能暂时实现了一个无后台的纯前端评论块,没错,纯前台,使用的大佬们的第三方接口,承蒙分享,其他的基本跟上一个板块类似,数据传递,返回模板


    image.png
    def detail(request, src):
        ##   src  ==  歌曲名字
        song_name = []
        singer_name = []
        pic_src = []
        song_name.append(src)
        singer_name.append(src.split(' - ')[0])
        pic_src.append("https://maya-picture.oss-cn-beijing.aliyuncs.com/"+src+".jpg")
        context = {}
        context['result'] = list(zip(song_name,singer_name,pic_src))
        print("song_name:%s,singer:%s,pic:%s" %(song_name, singer_name, pic_src))
        return render(request, 'file/search_detail.html', context)
    

    用户模块

    注册和登录功能参考的都是Django自带的auth模块,结合了[邮件](# https://docs.djangoproject.com/en/2.0/topics/email/)模块,利用ajax动态加载数据,实现即时传递以及数据校验,用户模块的话是可以在admin后台看到信息的,进行添加删除,邮件设置的时候校验码和邮箱类型设置得注意,按照官网模板进行设置就好了,这一块的功能无非就是注册登录,密码修改、邮箱验证、名字修改、忘记密码,退出登录这一些,都比较简单,简单展示下基础实现的代码,更多涉及数据校验之类的详情参考源码

    image.png image.png
    def login(request):
        if request.method == 'POST':
            login_form = LoginForm(request.POST)
            if login_form.is_valid():
                user = login_form.cleaned_data['user']
                auth.login(request, user)
                return redirect(request.GET.get('from', reverse('home')))
        else:
            login_form = LoginForm()
    
        context = {}
        context['login_form'] = login_form
        return render(request, 'user/login.html', context)
    
    def register(request):
        if request.method == 'POST':
            reg_form = RegForm(request.POST, request=request)
            if reg_form.is_valid():
                username = reg_form.cleaned_data['username']
                email = reg_form.cleaned_data['email']
                password = reg_form.cleaned_data['password']
                # 创建用户
                user = User.objects.create_user(username, email, password)
                user.save()
                # 清除session
                del request.session['register_code']
                # 登录用户
                user = auth.authenticate(username=username, password=password)
                auth.login(request, user)
                return redirect(request.GET.get('from', reverse('home')))
        else:
            reg_form = RegForm()
    
        context = {}
        context['reg_form'] = reg_form
        return render(request, 'user/register.html', context)
        
    def logout(request):
        auth.logout(request)
        return redirect(request.GET.get('from', reverse('home')))
    
    def user_info(request):
        context = {}
        return render(request, 'user/user_info.html', context)
    

    总结

      项目难点确实不大,主要是熟悉Django以及oss的工作流程,借此也熟悉了很多python的模块,诸如上传下载还有os模块,还有对字符串的处理,列表、字典、元组的转换传递,这里只是简单展示介绍了实现流程以及基础代码,用户模块以及文件处理里面也有涉及到自定义标签、数据校验、Django表单、文件和邮件处理,完整代码可以参考我的Github

    相关文章

      网友评论

        本文标题:Django案例 - 音乐网站实现

        本文链接:https://www.haomeiwen.com/subject/yudbcqtx.html