Django多对多字段报错:不存在root_post_Picture表
相关代码
models.py
class Pictures(models.Model): Post_id=models.IntegerField() Post_type=models.CharField(max_length=15) Picture = models.ImageField(upload_to="images/posts") class Files(models.Model): Post_id = models.IntegerField() Post_type = models.CharField(max_length=15) File = models.FileField(upload_to="documents/posts",validators=[documentvalidator]) class Videos(models.Model): Post_id = models.IntegerField() Post_type = models.CharField(max_length=15) Video = models.FileField(upload_to="videos/posts",validators=[videovalidator]) class Post(models.Model): post = models.CharField(max_length=900) Date = models.DateTimeField(default=django.utils.timezone.now) Picture=models.ManyToManyField(Pictures, blank=True) File = models.ManyToManyField(Files, blank=True) Video = models.ManyToManyField(Videos, blank=True) likes=models.IntegerField(default=0) dislikes = models.IntegerField(default=0) coments = models.IntegerField(default=0)
views.py
def postcreation(request): Videoarray=[] Picturearray=[] Filearray=[] form=AbsolutePostForm(request.GET) file = Fileform(request.FILES) pic = PictureForm(request.FILES) vid = VideoForm(request.FILES) if request.method=="POST": file = Fileform(request.FILES) if "File" in request.POST: if file.is_valid(): File=Files(Post_type="posts",Post_id=get_id_generation("postids.txt"),File=request.FILES["File"]) File.save() Filearray.append(File) print("file") return HttpResponse("file") pic = PictureForm(request.FILES) if "Picture" in request.FILES: if pic.is_valid(): Picture = Pictures(Post_type="posts", Post_id=get_id_generation("postids.txt"),Picture=request.FILES["Picture"]) Picture.save() Picturearray.append(Picture) print("pic") return HttpResponse("picture") vid = VideoForm(request.FILES) if "Video" in request.FILES: if vid.is_valid(): Video = Videos(Post_type="posts", Post_id=get_id_generation("postids.txt"),Video=request.FILES["Video"]) Video.save() print("vid") Videoarray.append(Video) if "Postcoment" in request.POST: form = AbsolutePostForm(request.POST) if form.is_valid(): post=form.cleaned_data["Postcoment"] Main=Post(post=post) Main.save() for obj in Filearray: Main.File.add(obj) for obj in Videoarray: Main.File.add(obj) for obj in Picturearray: Main.File.add(obj) return HttpResponse("welldone") context={"form":form,"pic": pic,"file":file,"vid":vid} return render(request,"postcreationpage.html",context)
forms.py
class AbsolutePostForm(forms.Form): Postcoment=forms.CharField(label="",required=False,max_length=700, widget=(forms.Textarea(attrs={"required": "True",'rows':"30", 'cols':"60", 'class':"postgrid", 'placeholder':"DECRIVEZ VOTRE POSTE"}))) class Fileform(forms.Form): File = forms.FileField(label="",required=False,widget=(forms.FileInput(attrs={"class":"invisible"})), validators=[documentvalidator]) class PictureForm(forms.Form): Picture = forms.ImageField(label="",required=False,widget=(forms.FileInput(attrs={"class":"invisible"}))) class VideoForm(forms.Form): Video = forms.FileField(label="",required=False,widget=(forms.FileInput(attrs={"class":"invisible"})),validators=[videovalidator])
模板代码
<div class="panel"> <div class="seperate"> <div class="attachements"> <div style="position: relative;"> <div style="width:40px; height: 35px; "> <form action="" method="POST" enctype="multipart/form-data"> {% csrf_token %} {{ pic }} <button type="submit" class="submiters">sauvegarder l'image choisie</button> </form> </div> <img src="{% static 'im.png' %}" class="pinner"> </div> <div style="position: relative;"> <div style=" width:40px; height: 35px; "> <form action="" method="POST" enctype="multipart/form-data"> {% csrf_token %} {{ vid }} <button type="submit" class="submiters" style="top: 100px;">sauvegarder la video choisie</button> </form> </div> <img src="{% static 'vid.png' %}" class="pinner"> </div> <div style="position: relative;"> <div style=" width:40px; height: 35px; "> <form action="" method="POST" enctype="multipart/form-data"> {% csrf_token %} {{ file }} <button type="submit" class="submiters" style="top: 150px;">sauvegarder le document choisi</button> </form> </div> <img src="{% static 'doc.png' %}" class="pinner"> </div> </div> <div> <form action="" method="POST" enctype="multipart/form-data"> {% csrf_token %} {{ form }} <br> <br> <button type="submit">POSTER</button> </form> </div> </div>
问题原因
模型关联逻辑重复:你同时用了两种方式关联Post和媒体模型:一是在
Pictures/Files/Videos里加Post_id手动关联,二是在Post里用ManyToManyField自动关联。这会让Django ORM混乱,导致多对多的中间表没有被正确生成。视图代码错误:在关联媒体到Post时,你把Video和Picture都错误地加到了
Main.File字段里,这不仅逻辑错误,还会让ORM的关联操作异常。迁移文件未正确生成:因为模型逻辑冲突,第一次生成的迁移文件可能没有包含多对多中间表的创建语句,导致数据库里没有
root_post_Picture这张表。
解决方案
1. 修正模型设计,移除手动关联字段
删掉Pictures/Files/Videos中的Post_id和Post_type,让多对多字段自动维护关联:
# 修改后的models.py class Pictures(models.Model): Picture = models.ImageField(upload_to="images/posts") class Files(models.Model): File = models.FileField(upload_to="documents/posts", validators=[documentvalidator]) class Videos(models.Model): Video = models.FileField(upload_to="videos/posts", validators=[videovalidator]) class Post(models.Model): post = models.CharField(max_length=900) Date = models.DateTimeField(default=django.utils.timezone.now) Picture = models.ManyToManyField(Pictures, blank=True) File = models.ManyToManyField(Files, blank=True) Video = models.ManyToManyField(Videos, blank=True) likes = models.IntegerField(default=0) dislikes = models.IntegerField(default=0) coments = models.IntegerField(default=0)
2. 重新生成并执行迁移
# 删除旧的初始迁移文件(如果之前的迁移已经执行过,注意备份数据) rm root/migrations/0001_initial.py # 生成新的迁移文件 python manage.py makemigrations # 同步数据库 python manage.py migrate
3. 修正视图中的关联错误
把错误的关联代码改成对应字段:
# 修改views.py中的这段代码 if form.is_valid(): post = form.cleaned_data["Postcoment"] Main = Post(post=post) Main.save() for obj in Filearray: Main.File.add(obj) for obj in Videoarray: Main.Video.add(obj) # 这里改成Video字段 for obj in Picturearray: Main.Picture.add(obj) # 这里改成Picture字段 return HttpResponse("welldone")
4. 修复表单提交的无状态问题(重要)
当前视图中,每次上传媒体后都会返回HttpResponse,导致Filearray/Picturearray/Videoarray里的数据会丢失(HTTP请求是无状态的)。建议用session临时存储已上传的媒体ID:
比如,保存图片时把ID存入session:
# 保存Picture的代码修改 if pic.is_valid(): Picture = Pictures(Picture=request.FILES["Picture"]) Picture.save() # 存入session request.session['picture_ids'] = request.session.get('picture_ids', []) + [Picture.id] print("pic") return HttpResponse("picture")
提交Post时再从session取出并关联:
# 提交Post的代码修改 if form.is_valid(): post = form.cleaned_data["Postcoment"] Main = Post(post=post) Main.save() # 关联文件 file_ids = request.session.get('file_ids', []) for fid in file_ids: f = Files.objects.get(id=fid) Main.File.add(f) # 关联视频 video_ids = request.session.get('video_ids', []) for vid in video_ids: v = Videos.objects.get(id=vid) Main.Video.add(v) # 关联图片 picture_ids = request.session.get('picture_ids', []) for pid in picture_ids: p = Pictures.objects.get(id=pid) Main.Picture.add(p) # 清空session del request.session['file_ids'] del request.session['video_ids'] del request.session['picture_ids'] return HttpResponse("welldone")
内容的提问来源于stack exchange,提问作者Lord vic
相关产品推荐
相关产品推荐

