三種方式建立多對多外鍵方式及其優缺點。html
class Class(models.Model): id = models.AutoField(primary_key=True) # 主鍵 cname = models.CharField(max_length=32) # 班級名稱 first_day = models.DateField() # 開班時間 class Teacher(models.Model): tname = models.CharField(max_length=32) # 自定義第三張表,經過外鍵關聯上面兩張表 class Teacher2Class(models.Model): teacher = models.ForeignKey(to="Teacher") the_class = models.ForeignKey(to="Class") class Meta: unique_together = ("teacher", "the_class")
class Class(models.Model): id = models.AutoField(primary_key=True) # 主鍵 cname = models.CharField(max_length=32) # 班級名稱 first_day = models.DateField() # 開班時間 class Teacher(models.Model): tname = models.CharField(max_length=32) # 經過ManyToManyField自動建立第三張表 cid = models.ManyToManyField(to="Class", related_name="teachers")
class Class(models.Model): id = models.AutoField(primary_key=True) # 主鍵 cname = models.CharField(max_length=32) # 班級名稱 first_day = models.DateField() # 開班時間 class Teacher(models.Model): tname = models.CharField(max_length=32) # 經過ManyToManyField和手動建立第三張表 cid = models.ManyToManyField(to="Class", through="Teacher2Class", through_fields=("teacher", "the_class")) class Teacher2Class(models.Model): teacher = models.ForeignKey(to="Teacher") the_class = models.ForeignKey(to="Class") class Meta: unique_together = ("teacher", "the_class")
class Teacher(models.Model): tname = models.CharField(max_length=32) cid = models.ManyToManyField(to="Class", related_name="teachers")
url(r'^teacher_list/$', app01_views.teacher_list, name="teacher_list"),
def teacher_list(request): teacher_list = models.Teacher.objects.all() return render(request, "teacher_list.html", {"teacher_list": teacher_list})
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>老師信息頁面</title> </head> <body> <a href="{% url 'add_teacher' %}">添加新老師</a> <table border="1"> <thead> <tr> <th>#</th> <th>id</th> <th>老師姓名</th> <th>授課班級</th> <th>操做</th> </tr> </thead> <tbody> {% for teacher in teacher_list %} <tr> <td>{{ forloop.counter }}</td> <td>{{ teacher.id }}</td> <td>{{ teacher.tname }}</td> <td> {% for class in teacher.cid.all %} {% if forloop.last %} {{ class.cname }} {% else %} {{ class.cname }}, {% endif %} {% endfor %} </td> <td> <a href="{% url 'delete_teacher' teacher.id %}">刪除</a> <a href="{% url 'edit_teacher' teacher.id %}">編輯</a> </td> </tr> {% endfor %} </tbody> </table> </body> </html>
url(r'^delete_teacher/(?P<tid>\d+)$', app01_views.delete_teacher, name="delete_teacher"),
def delete_teacher(request, tid): models.Teacher.objects.filter(id=tid).delete() return redirect(reverse("teacher_list"))
在老師列表頁面添加一個刪除的連接。前端
<a href="{% url 'delete_teacher' teacher.id %}">刪除</a>
url(r'^add_teacher/$', app01_views.add_teacher, name="add_teacher"),
def add_teacher(request): if request.method == "POST": tname = request.POST.get("tname") class_ids = request.POST.getlist("class_id") new_teacher = models.Teacher.objects.create(tname=tname) # 查詢出全部被選中的班級信息 class_objs = models.Class.objects.filter(id__in=class_ids) # 將老師的授課班級設置爲選中的班級, 如下四種均可以,注意何時加* new_teacher.cid.set(class_objs) # new_teacher.cid.add(*class_objs) # new_teacher.cid.add(*class_ids) # new_teacher.cid.set(class_ids) new_teacher.save() return redirect(reverse("teacher_list")) class_list = models.Class.objects.all() return render(request, "add_teacher.html", {"class_list": class_list})
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>添加老師</title> </head> <body> <form action="{% url 'add_teacher' %}" method="post"> {% csrf_token %} <p>老師姓名:<input type="text" name="tname"></p> <label for="class_id">授課班級:</label> <select name="class_id" id="class_id" multiple> {% for class in class_list %} <option value="{{ class.id }}">{{ class.cname }}</option> {% endfor %} </select> <p><input type="submit" value="提交"></p> </form> </body> </html>
url(r'^edit_teacher/(?P<tid>\d+)$', app01_views.edit_teacher, name="edit_teacher"),
def edit_teacher(request, tid): teacher_obj = models.Teacher.objects.get(id=tid) class_list = models.Class.objects.all() if request.method == "POST": tname = request.POST.get("tname") class_ids = request.POST.getlist("class_id") # 更新老師相關信息 teacher_obj.tname = tname teacher_obj.cid.set(class_ids) teacher_obj.save() # 必定記得更新完要保存 return redirect(reverse("teacher_list")) return render(request, "edit_teacher.html", {"class_list": class_list, "teacher": teacher_obj})
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>編輯老師信息</title> </head> <body> <form action="{% url 'edit_teacher' teacher.id %}" method="post"> {% csrf_token %} <p>老師姓名:<input type="text" name="tname" value="{{ teacher.tname }}"></p> <label for="class_id">授課班級:</label> <select name="class_id" id="class_id" multiple> {% for class in class_list %} {% if class in teacher.cid.all %} <option value="{{ class.id }}" selected>{{ class.cname }}</option> {% else %} <option value="{{ class.id }}">{{ class.cname }}</option> {% endif %} {% endfor %} </select> <p><input type="submit" value="提交"></p> </form> </body> </html>
正向查詢(由老師表查詢班級表)app
>>> teacher_obj = models.Teacher.objects.first() >>> teacher_obj.cid.all() # 查詢該老師授課的全部班級 <QuerySet [<Class: Class object>, <Class: Class object>]>
反向查詢(由班級表反向查詢老師表)oop
>>> class_obj = models.Class.objects.first() >>> class_obj.teachers.all() # 此處用到的是related_name,若是不設置的話就用默認的表名_set <QuerySet [<Teacher: Teacher object>, <Teacher: Teacher object>, <Teacher: Teacher object>]>