今天的Django教训汇总:多对多模型的建立、一对多模型的反向关联-20210329

1.Django 3.1.3新建project时会报错。

C:\Users\season\workspace2>django-admin.py startproject tango_with_django_project

报错信息如下:

ImportError(
        'django-admin.py was deprecated in Django 3.1 and removed in Django '
        '4.0. Please manually remove this script from your virtual environment '
        'and use django-admin instead.'

认真阅读报错信息,就会发现解决措施“use django-admin instead of django-admin.py”。

C:\Users\season\workspace2>django-admin startproject tango_with_django_project

2.多对多关系

多对多关系建立:最好使用默认id作为主键,不要取primary_key=True,否则多对多关系可能无法建立。

https://docs.djangoproject.com/zh-hans/3.1/topics/db/models/

Django 允许你指定用于控制多对多关系的模型。你可以在中间模型当中添加额外的字段。在实例化 ManyToManyField 的时候使用 through 参数指定多对多关系使用哪个中间模型。**最好使用默认id作为主键,不要取primary_key=True,否则多对多关系可能无法建立。**例子代码如下:

from django.db import models


class Employee(models.Model):
    eid = models.CharField(max_length=200,default='1')
    name = models.CharField(max_length=200,null=True)
    dept_code = models.CharField(max_length=200,null=True)
    GENDER_CHOICES = (
        (u'Male', u'Male'),
        (u'Female', u'Female'),
    )
    gender = models.CharField(max_length=200,choices=GENDER_CHOICES,null=True)
    on_board = models.BooleanField(null=True)
    Range_CHOICES = (
        (u'R1', u'R1'),
        (u'R2', u'R2'),
        (u'R3', u'R3'),
        (u'R4', u'R4'),
    )
    Range = models.CharField(max_length=200,choices=Range_CHOICES,null=True)

    def __str__(self):
        return self.name


class Teacher(models.Model):
    tid = models.CharField(max_length=200,default='1')
    name = models.CharField(max_length=200,null=True)
    dept = models.CharField(max_length=200,null=True)
    GENDER_CHOICES = (
        (u'Male', u'Male'),
        (u'Female', u'Female'),
    )
    gender = models.CharField(max_length=200,choices=GENDER_CHOICES,null=True)
    on_board = models.BooleanField(null=True)
    GRADE_CHOICES = (
        (u'Junior', u'Junior'),
        (u'Middle', u'Middle'),
        (u'Senior', u'Senior'),
    )
    teacher_grade = models.CharField(max_length=200,choices=GRADE_CHOICES,null=True)

    def __str__(self):
        return self.name



class Subject(models.Model):
    Subject_id = models.CharField(max_length=200,default='1')
    subject_name = models.CharField(max_length=200)
    teacher = models.ForeignKey(Teacher, on_delete=models.CASCADE,null=True)
    employee = models.ManyToManyField(Employee, through='Employee_Subject')

    def __str__(self):
        return '%s.%s' % (self.Subject_id, self.subject_name)


class Employee_Subject(models.Model):
    subject = models.ForeignKey(Subject,on_delete=models.CASCADE)
    employee = models.ForeignKey(Employee,on_delete=models.CASCADE)


    def __str__(self):
        return '%s : %s' % (self.subject.subject_name, self.employee.name)

3.一对多的“反向” 关联

https://blog.csdn.net/jingxiao95/article/details/89035588

解释

反向查询:一查找多,是反向查找。
无外键类的具体对象.有外键的小写类名_set。
无外键类是一,有外键是多。
一的具体对象.多的类名小写_set 查到一的具体对象下的所有多的对象
eg:
一个出版社对应多本书,以出版社为标准查找书,反向查找。
一个出版社对象.书类_set 查到出版社下的书籍对象,这个书籍对象默认是一个QuerySet对象。
查到一个出版社具体对象下的所有的书。

清晰的例子:

model.py

#出版社类(表)
class Publisher(models.Model):
	pid = models.AutoField(primary_key=True)
	pname = models.CharField(max_length=32)


#书籍类(表)
class Books(models.Model):
	bid = models.AutoField(primary_key=True)
	bname = models.CharField(max_length=32)
	publisher_obj = models.ForeignKey('Publisher')
  • 展示出版社的方法一:
  • views.py内:
def show_publisher(request):
	# 获取出版社对象列表
	publisher_obj_list = models.Publisher.objects.all()
	# 获取书籍,通过书籍中的外键对象publisher_obj
	# 循环这个出版社对象列表,在书籍表中匹配每一个出版社对象,匹配到就返回书籍对象列表,没有就是空的对象列表,该书籍对象,有具体的出版社对象
	books_obj_list = []
	for publishers_obj in publisher_obj_list:
		#获取到books_obj可能是一个列表
		books_obj = models.Books.objects.filter(publisher_obj=publishers_obj)
		#将books_obj列表里面的每一个内容拿出来,加到列表内
		books_obj_list.extend(books_obj)
	return render(request, 'show_publisher.html',
				  {
    
    "publisher_obj_list": publisher_obj_list, "books_obj_list": books_obj_list})

template内

<table border="1">
<thead>
<tr>
    <th>序号</th>
    <th>出版社名字</th>
    <th>书籍</th>
</tr>
</thead>
<tbody>
{
    
    % for publisher_obj in publisher_obj_list %}
    <tr>
   	    #序号
        <td>{
    
    {
    
     forloop.counter }}</td>
        {
    
    # 出版社名字 #}
        <td>{
    
    {
    
     publisher_obj.pname }}</td>
        {
    
    # 书籍名字#}
         <td>
         循环书籍对象列表(每一个书籍都有一个对应的publisher_obj)
                {
    
    % for books_obj in  books_obj_list %}
         判断如果这个出版社对象与书籍的出版社对象相同,获取该书籍的名字
                    {
    
    % if publisher_obj == books_obj.publisher_obj %}{
    
    {
    
     books_obj.bname }}{
    
    % endif %}
                {
    
    % endfor %}
            {
    
    % endfor %}
            </td>
  • 展示出版社的方法二:
  • views.py
def show_publisher(request):
# 获取出版社对象列表
publisher_obj_list = models.Publisher.objects.all()
return render(request, 'show_publisher.html',
			  {
    
    "publisher_obj_list": publisher_obj_list,})    

template内

#反向查找:通过一查找多
#无外键的具体对象(一的具体对象).有外键的小写类名(多的类名小写)_set.all()
#反向查找默认返回的是一个QuerySet对象#}

        <td>
            {
    
    % for book_obj in publisher_obj.books_set.all %}{
    
    {
    
     book_obj.bname }}{
    
    % endfor %}

        </td>

4.admin界面无法删除数据库数据时,方法一:可以用SQLite Studio来强行删除。方法二:调整modoel中的__str__方法。

class Employee_Subject(models.Model):
    subject = models.ForeignKey(Subject,on_delete=models.CASCADE)
    employee = models.ForeignKey(Employee,on_delete=models.CASCADE)

    #def __str__(self):
        #return '%s : %s' % (self.subject.subject_name, self.employee.name)

5.我的例子

  • 界面
    在这里插入图片描述

  • models.py

from django.db import models


class Employee(models.Model):
    eid = models.CharField(max_length=200,default='1')
    name = models.CharField(max_length=200,null=True)
    dept_code = models.CharField(max_length=200,null=True)
    GENDER_CHOICES = (
        (u'Male', u'Male'),
        (u'Female', u'Female'),
    )
    gender = models.CharField(max_length=200,choices=GENDER_CHOICES,null=True)
    on_board = models.BooleanField(null=True)
    Range_CHOICES = (
        (u'R1', u'R1'),
        (u'R2', u'R2'),
        (u'R3', u'R3'),
        (u'R4', u'R4'),
    )
    Range = models.CharField(max_length=200,choices=Range_CHOICES,null=True)

    def __str__(self):
        return self.name


class Teacher(models.Model):
    tid = models.CharField(max_length=200,default='1')
    name = models.CharField(max_length=200,null=True)
    dept = models.CharField(max_length=200,null=True)
    GENDER_CHOICES = (
        (u'Male', u'Male'),
        (u'Female', u'Female'),
    )
    gender = models.CharField(max_length=200,choices=GENDER_CHOICES,null=True)
    on_board = models.BooleanField(null=True)
    GRADE_CHOICES = (
        (u'Junior', u'Junior'),
        (u'Middle', u'Middle'),
        (u'Senior', u'Senior'),
    )
    teacher_grade = models.CharField(max_length=200,choices=GRADE_CHOICES,null=True)

    def __str__(self):
        return self.name



class Subject(models.Model):
    Subject_id = models.CharField(max_length=200,default='1')
    subject_name = models.CharField(max_length=200)
    teacher = models.ForeignKey(Teacher, on_delete=models.CASCADE,null=True)
    employee = models.ManyToManyField(Employee, through='Employee_Subject')

    def __str__(self):
        return '%s.%s' % (self.Subject_id, self.subject_name)


class Employee_Subject(models.Model):
    subject = models.ForeignKey(Subject,on_delete=models.CASCADE)
    employee = models.ForeignKey(Employee,on_delete=models.CASCADE)


    def __str__(self):
        return '%s : %s' % (self.subject.subject_name, self.employee.name)
  • views.py
from django.shortcuts import render
from .models import Subject,Employee,Employee_Subject,Teacher
#from .models import Subject,Employee,Teacher


# Create your views here.

def index(request):
    Subject_list = Subject.objects.order_by('-Subject_id').all()
    Employee_Subject_list = Employee_Subject.objects.all()
    Teacher_list = Teacher.objects.all()
    subject_obj_list = []
    for Teacher_obj in Teacher_list:
        subject_obj = Subject.objects.filter(teacher = Teacher_obj)
        subject_obj_list.extend(subject_obj)

    context = {
    
    'Subject_list':Subject_list,
            'Employee_Subject_list':Employee_Subject_list,
            'Teacher_list':Teacher_list,
            'subject_obj_list':subject_obj_list,
            }
    return render(request,'myclass/index.html',context=context)

  • index.html
<html>
<head>
<title>notice</title>
</head>

<body>
<table>
    <p>课程信息</p>
    <tr align="center" style="color:White;background-color:#3366FF;font-family:微軟正黑體,Tahoma,Arial,微軟雅黑體;font-size:14px;">
    <th scope="col">Subject_id</th>
    <th scope="col">subject_name</th>
    <th scope="col">teacher.name</th>
    </tr>

    {
    
    % for item in Subject_list %}
    <tr align="center" valign="middle" style="color:Black;background-color:#EFF3FB;border-color:#E0E0E0;border-width:1px;border-style:solid;height:26px;">
    <td>{
    
    {
    
     item.Subject_id }}</td>
    <td>{
    
    {
    
     item.subject_name }}</td>
    <td>{
    
    {
    
     item.teacher.name }}</td>
    </tr>
    {
    
    % endfor %}
</table>

<table>
    <p>学员选课信息</p>
    <tr align="center" style="color:White;background-color:#3366FF;font-family:微軟正黑體,Tahoma,Arial,微軟雅黑體;font-size:14px;">
        <th scope="col">employee.name</th>
        <th scope="col">Subject_id</th>
        <th scope="col">subject_name</th>
        <th scope="col">teacher</th>
    </tr>

    {
    
    % for item in Employee_Subject_list %}
    <tr align="center" valign="middle" style="color:Black;background-color:#EFF3FB;border-color:#E0E0E0;border-width:1px;border-style:solid;height:26px;">
    <td>{
    
    {
    
     item.employee.name }}</td>
    <td>{
    
    {
    
     item.subject.Subject_id }}</td>
    <td>{
    
    {
    
     item.subject.subject_name }}</td>
    <td>{
    
    {
    
     item.subject.teacher.name }}</td>
    </tr>
    {
    
    % endfor %}
</table>

<table>
    <p>讲师信息</p>
    <tr align="center" style="color:White;background-color:#3366FF;font-family:微軟正黑體,Tahoma,Arial,微軟雅黑體;font-size:14px;">
        <th scope="col">tid</th>
        <th scope="col">name</th>
        <th scope="col">dept</th>
        <th scope="col">gender</th>
        <th scope="col">on_board</th>
        <th scope="col">teacher_grade</th>
        <th scope="col">subject_name</th>
    </tr>

    {
    
    % for item in Teacher_list %}
    <tr align="center" valign="middle" style="color:Black;background-color:#EFF3FB;border-color:#E0E0E0;border-width:1px;border-style:solid;height:26px;">
    <td>{
    
    {
    
     item.tid }}</td>
    <td>{
    
    {
    
     item.name }}</td>
    <td>{
    
    {
    
     item.dept }}</td>
    <td>{
    
    {
    
     item.gender }}</td>
    <td>{
    
    {
    
     item.on_board }}</td>
    <td>{
    
    {
    
     item.teacher_grade }}</td>
    <td>
        {
    
    % for subject_obj in  subject_obj_list %}
            {
    
    % if item == subject_obj.teacher %}
                    {
    
    {
    
     subject_obj.subject_name }}
            {
    
    % endif %}
        {
    
    % endfor %}
    </td>

    </tr>
    {
    
    % endfor %}
</table>


<table>
    <p>讲师信息2</p>
    <tr align="center" style="color:White;background-color:#3366FF;font-family:微軟正黑體,Tahoma,Arial,微軟雅黑體;font-size:14px;">
        <th scope="col">tid</th>
        <th scope="col">name</th>
        <th scope="col">dept</th>
        <th scope="col">gender</th>
        <th scope="col">on_board</th>
        <th scope="col">teacher_grade</th>
        <th scope="col">subject_name</th>
    </tr>

    {
    
    % for item in Teacher_list %}
    <tr align="center" valign="middle" style="color:Black;background-color:#EFF3FB;border-color:#E0E0E0;border-width:1px;border-style:solid;height:26px;">
    <td>{
    
    {
    
     item.tid }}</td>
    <td>{
    
    {
    
     item.name }}</td>
    <td>{
    
    {
    
     item.dept }}</td>
    <td>{
    
    {
    
     item.gender }}</td>
    <td>{
    
    {
    
     item.on_board }}</td>
    <td>{
    
    {
    
     item.teacher_grade }}</td>
    <td>
        {
    
    % for subject_item in  item.subject_set.all %}
            {
    
    {
    
     subject_item.subject_name }}
        {
    
    % endfor %}
    </td>

    </tr>
    {
    
    % endfor %}
</table>



</body>

猜你喜欢

转载自blog.csdn.net/m0_46629123/article/details/115305542