diff --git a/djangoProject2/.idea/.gitignore b/djangoProject2/.idea/.gitignore new file mode 100644 index 00000000..35410cac --- /dev/null +++ b/djangoProject2/.idea/.gitignore @@ -0,0 +1,8 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/djangoProject2/.idea/djangoProject2.iml b/djangoProject2/.idea/djangoProject2.iml new file mode 100644 index 00000000..52110e94 --- /dev/null +++ b/djangoProject2/.idea/djangoProject2.iml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/djangoProject2/.idea/inspectionProfiles/profiles_settings.xml b/djangoProject2/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 00000000..105ce2da --- /dev/null +++ b/djangoProject2/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/djangoProject2/.idea/misc.xml b/djangoProject2/.idea/misc.xml new file mode 100644 index 00000000..ef8935ed --- /dev/null +++ b/djangoProject2/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/djangoProject2/.idea/modules.xml b/djangoProject2/.idea/modules.xml new file mode 100644 index 00000000..cb71eb50 --- /dev/null +++ b/djangoProject2/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/djangoProject2/Movie recommendation system/__init__.py b/djangoProject2/Movie recommendation system/__init__.py new file mode 100644 index 00000000..aa60bed8 --- /dev/null +++ b/djangoProject2/Movie recommendation system/__init__.py @@ -0,0 +1,3 @@ +import pymysql + +pymysql.install_as_MySQLdb() \ No newline at end of file diff --git a/djangoProject2/Movie recommendation system/settings.py b/djangoProject2/Movie recommendation system/settings.py new file mode 100644 index 00000000..04049287 --- /dev/null +++ b/djangoProject2/Movie recommendation system/settings.py @@ -0,0 +1,121 @@ +""" +Django settings for djangoProject2 project. + +Generated by 'django-admin startproject' using Django 5.0.6. + +For more information on this file, see +https://docs.djangoproject.com/en/5.0/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/5.0/ref/settings/ +""" +import os + +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + +SECRET_KEY = 'django-insecure-p&$li#_laqa0p0il+ibs8cxcitn6d8s$iv8p05_7g=l)+1tp&s' + + +DEBUG = True + +ALLOWED_HOSTS = [] + + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'movie' +] + +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 = 'djangoProject2.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 = 'djangoProject2.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/5.0/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.mysql', + 'NAME': 'db_movie_recommend', + 'USER': 'root', + 'PASSWORD': '123456', + 'HOST': 'localhost', + 'PORT': '3306', + } +} + + +# Password validation +# https://docs.djangoproject.com/en/5.0/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/5.0/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/5.0/howto/static-files/ + +STATIC_URL = 'static/' + +STATICFILES_DIRS=[ + os.path.join(BASE_DIR,'static'), +] + + diff --git a/djangoProject2/Movie recommendation system/urls.py b/djangoProject2/Movie recommendation system/urls.py new file mode 100644 index 00000000..4ea51103 --- /dev/null +++ b/djangoProject2/Movie recommendation system/urls.py @@ -0,0 +1,11 @@ +from django.contrib import admin +from django.urls import path,include + +from.views import index,star + + +urlpatterns = [ + path('admin/', admin.site.urls), + path('',index), + path('movie/',include('movie.urls')), +] diff --git a/djangoProject2/Movie recommendation system/views.py b/djangoProject2/Movie recommendation system/views.py new file mode 100644 index 00000000..88fb8298 --- /dev/null +++ b/djangoProject2/Movie recommendation system/views.py @@ -0,0 +1,8 @@ +from django.shortcuts import render + + +def index(request): + return render(request,'index.html') + +def star(request): + return render(request,'movie/star.html') diff --git a/djangoProject2/Movie recommendation system/wsgi.py b/djangoProject2/Movie recommendation system/wsgi.py new file mode 100644 index 00000000..9cf72e9d --- /dev/null +++ b/djangoProject2/Movie recommendation system/wsgi.py @@ -0,0 +1,6 @@ +import os +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Movie recommendation system.settings') + +application = get_wsgi_application() diff --git a/djangoProject2/manage.py b/djangoProject2/manage.py new file mode 100644 index 00000000..1db567e5 --- /dev/null +++ b/djangoProject2/manage.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoProject2.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "项目未安装 Django 库,请安装 Django 库。" + ) from exc + execute_from_command_line(sys.argv) + +if __name__ == '__main__': + main() diff --git a/djangoProject2/movie/__init__.py b/djangoProject2/movie/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/djangoProject2/movie/__pycache__/__init__.cpython-312.pyc b/djangoProject2/movie/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 00000000..7f509166 Binary files /dev/null and b/djangoProject2/movie/__pycache__/__init__.cpython-312.pyc differ diff --git a/djangoProject2/movie/__pycache__/models.cpython-312.pyc b/djangoProject2/movie/__pycache__/models.cpython-312.pyc new file mode 100644 index 00000000..1cca1d9c Binary files /dev/null and b/djangoProject2/movie/__pycache__/models.cpython-312.pyc differ diff --git a/djangoProject2/movie/admin.py b/djangoProject2/movie/admin.py new file mode 100644 index 00000000..7ccc7647 --- /dev/null +++ b/djangoProject2/movie/admin.py @@ -0,0 +1,83 @@ +from django.contrib import admin +from movie.model import User,Genre,Movie_hot,Movie_rating,Movie_similarity + + +admin.site.site_title="电影推荐系统后台管理系统" +admin.site.site_header="电影推荐系统——后台管理系统" +admin.site.index_title="电影推荐系统" + + +@admin.register(User) +class UserAdmin(admin.ModelAdmin): + list_display=['id','name','password','email'] + search_fields=['name','email'] + list_per_page=12 + ordering=['id'] + + +@admin.register(Genre) +class GenreAdmin(admin.ModelAdmin): + list_display=['id','name'] + search_fields=['name'] + list_per_page=12 + ordering=['id'] + +@admin.register(Movie) +class MovieAdmin(admin.ModelAdmin): + list_display=['id','name','imdb_id','time','release_time','intro','director','writers','actor'] + search_fields=['name','intro','writers','actor'] + list_per_page=6 + ordering=['id'] + +@admin.register(Movie_hot) +class Movie_hotAdmin(admin.ModelAdmin): + list_display=['id','movie','rating_number'] + search_fields=['movie'] + list_per_page=6 + ordering=['-rating_number'] + + +@admin.register(Movie_rating) +class Movie_ratingAdmin(admin.ModelAdmin): + list_display=['id','user','movie','score','comment'] + search_fields=['user','movie'] + list_per_page=6 + ordering=['-score'] + + +@admin.register(Movie_similarity) +class Movie_similarityAdmin(admin.ModelAdmin): + list_display=['id','movie_source','movie_target','similarity'] + search_fields=['movie_source','movie_source'] + list_per_page=6 + ordering=['-similarity'] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/djangoProject2/movie/apps.py b/djangoProject2/movie/apps.py new file mode 100644 index 00000000..2ed287c0 --- /dev/null +++ b/djangoProject2/movie/apps.py @@ -0,0 +1,7 @@ +from django.apps import AppConfig + + + +class MovieConfig(AppConfig): + name = 'movie' + verbose_name='电影推荐系统' \ No newline at end of file diff --git a/djangoProject2/movie/context processors.py b/djangoProject2/movie/context processors.py new file mode 100644 index 00000000..b2a396b8 --- /dev/null +++ b/djangoProject2/movie/context processors.py @@ -0,0 +1,12 @@ +from.models import User + +def movie_user(request): + user_id=request.session.get('user_id') + context={} + if user_id: + try: + user=User.objects.get(pk=user_id) + context['movie_user']=user + except: + pass + return context diff --git a/djangoProject2/movie/forms.py b/djangoProject2/movie/forms.py new file mode 100644 index 00000000..6d6686aa --- /dev/null +++ b/djangoProject2/movie/forms.py @@ -0,0 +1,96 @@ +from django import forms + +from movie.models import User,Movie_rating + +class RegisterForm(forms.ModelForm): + password_repeat=forms.CharField(max_length=256) + + def get_erros(self): + erros=self.erros.get_json_data() + erros_lst=[] + for messages in erros.values(): + for messages_dict in messages: + for key,message in message_dict.items(): + if key=='messasge': + erros_lst.apppend(message) + return erros_lst + + + def clean(self): + cleaned_data=super(RegisterForm,self).clean() + pwd=cleaned_data.get('password') + password_repeat=cleaned_data.get('password_repeat') + if pwd!=password_repeat: + raise forms.ValidationError(message='两次密码输入不一致!') + return cleaned_data + + + class Meta: + model=User + fields=['name','password','email'] + +class LoginForm(forms.modelForm): + name=forms.CharField(max_length=128) + remember=forms.IntegerField(required=False) + + class Mate: + model=User + fields=['password'] + + def get_error(self): + errors=self.errors.get_json_data() + errors_lst=[] + for messages in errors.values(): + for message_dict in messsages: + for key.message in message_dict.items(): + if key=='messasge': + errors_lst.append(message) + return errors_lst + +class CommentForm(forms.ModelForm): + def clean(self) + cleaned_data=super(CommentForm,self).clean() + score=cleaned_data.get('score') + if score<0 or score>5: + raise forms.ValidationError(message='评分不能为空!') + else: + return cleaned_data + + class Meta: + model=Movie_rating + fields=['score','comment'] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/djangoProject2/movie/models.py b/djangoProject2/movie/models.py new file mode 100644 index 00000000..5f8ea41f --- /dev/null +++ b/djangoProject2/movie/models.py @@ -0,0 +1,141 @@ +from django.db import models +from django.db.models import Avg + + +class Genre(models.Model): + name = models.CharField(max_length=100,verbose_name="类型") + + class Meta: + db_table='Genre' + verbose_name='电影类型' + verbose_name_plural='电影类型' + + def __str__(self): + return self.name + + +class Movie(models.Model): + name=models.CharField(max_length=256,verbose_name="电影名") + imdb_id=models.integerField(verbose_name="imdb_id") + time=models.CharField(max_length=256,blank=True,verbose_name="时长") + genre=models.ManyToManyField(Genre,verbose_name="类型") + release_time=models.CharField(max_length=256,blank=True,verbose_name="发行时间") + intro=models.TextField(blank=True,verbose_name="简介") + director=models.CharField(max_length=256,blank=True,verbose_name="导演") + actor=models.CharField(max_length=256,blank=True,verbose_name="演员") + writers=models.CharField(max_length=256,blank=True,verbose_name="编剧") + movie_similarity=models.ManyToManyField('self',through="Movie_similarity",symmetrical=False,verbose_name="相似电影") + + + class Meta: + db_table='Movie' + verbose_name='电影信息' + verbose_name_plural='电影信息' + + def __str__(self): + return f"" + + + def get_score(self): + result_dct=self.movie_rating_set.aaggregate(Avg('score')) + try: + result=round(result_dct['score__avg'],1) + except TypeError: + return 0 + else: + return result + + def get_user_score(self,user): + return self.movie_rating_set.filter(user=user).values('score') + + def get_score_int_range(self): + return range(int(self.get_score())) + + def get_genre(self): + genre_dct=self.genre.all().values('name') + genre_lst=[] + for dct in genre_dct.values(): + genre_lst.append(dct['name']) + return genre_lst + + + def get_similarity(self,k=5): + similarity_movies=self.movie_similarity.all()[:k] + return similarity_movies + +class Movie_similarity(models.Model): + movie_source=models.ForeignKey(Movie,related_name='movie_source',on_delete=models.CASCADE) + movie_target=models.ForeignKey(Movie,related_name='movie_target',on_delete=models.CASCADE) + similarity=models.FloatField(verbose_name="相似度") + + class Meta: + verbose_name='电影相似度' + verbose_name_plural='电影相似度' + + +class User(models.Model): + name=models.CharField(max_length=128,unique=True,verbose_name="用户名") + password=models.CharField(max_length=256,verbose_name="密码") + email=models.EmailField(unique=True,verbose_name="邮箱") + rating_movies=models.ManyToManyField(Movie,through="Movie_rating") + + + + def __str__(self): + return self.name + + class Meta: + db_table='Usser' + verbose_name='用户信息' + verbose_name_plural='用户信息' + +class Movie_rating(models.Model): + user=models.ForeignKey(Usser,on_delete=models.CASCADE,unique=False,verbose_name="用户") + movie=models.ForeignKey(Movie,on_delete=models.CASCADE,unique=False,verbose_name="电影") + score=models.FloatField(verbose_name="评分") + comment=models.TextField(blank=True,verbose_name="评论") + + class Meta: + db_table='Movie_rating' + verbose_name='电影评分信息' + verbose_name_plural='电影评分信息' + +class Movie_hot(model.Model): + movie=models.ForeignKey(Movie,on_delete=models.CASCADE,verbose_name="电影名") + rating_number=models.IntegereField(verbose_name="评分人数") + + + class Meta: + db_table='Movie_hot' + verbose_name='最热电影' + verbose_name_plural='最热电影' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +