Django+xadmin to build an online education platform (4)

Django+xadmin to build an online education platform (4)

Code

github download

7. the function of the teaching institution

7.1. Template inheritance

(1) Create a motherboard

Copy org-list.html to the templates directory, create a new base.html, and cut the content of org-list.html into it

Then modify the address of the static file (css, is, image and media)

(2) Organization homepage routing

from organization.views import OrgView

path('org_list/',OrgView.as_view(),name ='org_list'),

(3) Institutional views

class OrgView(View):
    '''Course institution'''
    def get(self,request):
        return render(request,'org-list.html')

(4) org-list.html inherits base

{#templates/org-list.html#}

{% extends'base.html' %}

{% block title %}
    List of Course Institutions
{% endblock %}

Visit: http://127.0.0.1:8000/org_list/You can see the org_list page

(5) Modify the base template

Cut the contents of the two blocks of custom_bread and content in base into org-list.html

base.html

org-list.html

7.2. Add cities and course institutions

 (1) Enter the xadmin background to add a city

 The organization here is static and fixed, and the region is dynamic, obtained from the database

 (2) Modify the models of the institution and add an institution category field

organization/models.py:

class CourseOrg(models.Model):
    ORG_CHOICES = (
        ("pxjg", u"training organization"),
        ("gx", u"high school"),
        ("gr", u"personal"),
    )

#Add field
 category = models.CharField(max_length=20, choices=ORG_CHOICES, verbose_name=u"organization category", default="pxjg")
class CourseOrg(models.Model):
    ORG_CHOICES = (
        ("pxjg", u"training organization"),
        ("gx", u"high school"),
        ("gr", u"personal"),
    )
    name = models.CharField('Organization Name',max_length=50)
    desc = models.TextField('Organization Description')
    category = models.CharField(max_length=20, choices=ORG_CHOICES, verbose_name=u"organization category", default="pxjg")
    click_nums = models.IntegerField('Number of clicks',default=0)
    fav_nums = models.IntegerField('Number of collections',default=0)
    image = models.ImageField('logo',upload_to='org/%Y%m',max_length=100)
    address = models.CharField('Organization address',max_length=150,)
    city ​​= models.ForeignKey(CityDict,verbose_name='City',on_delete=models.CASCADE)
    add_time = models.DateTimeField(default=datetime.now)

    class Meta:
        verbose_name ='Course institution'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name

After adding makemigrations-->>migrate

(3) Add organization

Upload the picture of the organization when adding organization information

Create a new directory "media" under the project directory to store uploaded pictures

In the setting, we need to configure which root directory we store the file under

#settings.py

# Set the path of the uploaded file
MEDIA_URL ='/media/'
MEDIA_ROOT = os.path.join(BASE_DIR,'media') #Specify the root directory

Will splice the complete path with upload

"/Media/org/2018/month/picture name"

Then add ten institutions in the background

7.3. Show course institution and city

 (1) Write the view function organization/views.py

class OrgView(View):
    '''Course institution'''
    def get(self,request):
        # Take out all course institutions
        all_orgs = CourseOrg.objects.all()
        org_onums = all_orgs.count()
        # Take out all cities
        all_citys = CityDict.objects.all()
        return render(request, "org-list.html", {
            "all_orgs": all_orgs,
            "all_citys": all_citys,
            'org_onums':org_onums,
        })

(2) Modify org-list.html

Show the total number of institutions

Show city

Display organization

Then you have to do the following settings

How to convert image field into image address

 The image in the database is saved in string format. It is a relative path. It cannot be retrieved directly. The path must be completed.

data-url="{{ MEDIA_URL }}{{ course_org.image }}"
MEDIA_URL ='/media/', this is set in the previous settings

To use {{ MEDIA_URL }}, first add a media processor in TEMPLATES in settings:'django.core.context_processors.media'

 Then add the URL that handles the corresponding path of the image

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',
                #Add image processor, in order to add MEDIA_URL in front of the course list
                'django.template.context_processors.media',
            ],
        },
    },
]

 urls.py

from django.views.static import serve
from MxOnline.settings import MEDIA_ROOT


# Process the url displayed by the picture, use Django's own serve, and pass in the parameters to tell it which path to find, we have the configured path MEDIAROOT
re_path(r'^media/(?P<path>.*)', serve, {"document_root": MEDIA_ROOT })

4.places

7.4. Paging function

Use the pagination artifact django-pure-pagination for pagination, the usage method is introduced on github

 (1) Installation

pip install django-pure-pagination

(2) Add in settings

INSTALLED_APPS = (
    ...
    'pure_pagination',
)

(3) How to use in views

class OrgView(View):
    '''Course institution'''

    def get(self, request):
        # All course institutions
        all_orgs = CourseOrg.objects.all()
        # How many institutions
        org_nums = all_orgs.count()
        # All cities
        all_citys = CityDict.objects.all()
        # Pagination of course institutions
        # Try to get the page parameters passed by the front desk get request
        # If it is an illegal configuration parameter, return to the first page by default
        try:
            page = request.GET.get('page', 1)
        except PageNotAnInteger:
            page = 1
        # Here refers to five from allorg, each page shows five
        p = Paginator(all_orgs, 5, request=request)
        orgs = p.page(page)

        return render(request, "org-list.html", {
            "all_orgs": orgs,
            "all_citys": all_citys,
            "org_nums": org_nums,
        })

(4) Modify org-list.html

 This becomes "all_orgs.object_list"

Paging function

<div class="pageturn">
    <ul class="pagelist">
        {% if all_orgs.has_previous %}
            <li class="long"><a href="?{{ all_orgs.previous_page_number.querystring }}">Previous page</a></li>
        {% endif %}

        {% for page in all_orgs.pages %}
            {% if page %}
                {% ifequal page all_orgs.number %}
                    <li class="active"><a href="?{{ page.querystring }}">{{ page }}</a></li>
                {% else %}
                    <li><a href="?{{ page.querystring }}" class="page">{{ page }}</a></li>
                {% endifequal %}
            {% else %}
                <li class="none"><a href="">...</a></li>
            {% endif %}
        {% endfor %}
        {% if all_orgs.has_next %}
            <li class="long"><a href="?{{ all_orgs.next_page_number.querystring }}">Next page</a></li>
        {% endif %}
    </ul>
</div>

Changed to display 2 lists per page, as follows:

7.5. List filter function

(1) City list filtering

  • Click on the city to filter out the corresponding course institutions
  • The default "All" is in the'active' state (green), if a city is clicked, the city should be in the'active' state
  • When the user clicks on the city, the id of the city should be passed to the backend, and then the backend is passed to the template. Yes, you can know which city is selected, and then add ``active''

Background processing city filtering

class OrgView(View):
    '''Course institution'''

    def get(self, request):
        # All course institutions
        all_orgs = CourseOrg.objects.all()
        # How many institutions
        org_nums = all_orgs.count()
        # All cities
        all_citys = CityDict.objects.all()

        city_id = request.GET.get('city','')
        if city_id:
            all_orgs = all_orgs.filter(city_id=int(city_id))

        # Pagination of course institutions
        # Try to get the page parameters passed by the front desk get request
        # If it is an illegal configuration parameter, return to the first page by default
        try:
            page = request.GET.get('page', 1)
        except PageNotAnInteger:
            page = 1
        # Here refers to five from allorg, each page shows five
        p = Paginator(all_orgs, 2, request=request)
        orgs = p.page(page)

        return render(request, "org-list.html", {
            "all_orgs": orgs,
            "all_citys": all_citys,
            "org_nums": org_nums,
            'city_id':city_id,
        })

Front page

<h2>Location</h2>
    <div class="more">More</div>
    <div class="cont">
        <a href="?ct="><span class="{% ifequal city_id'' %}active2{% endifequal %}">All</span></a>
        {% for city in all_citys %}
            <a href="?city={{ city.id }}"><span class="{% ifequal city.id|stringformat:'i' city_id %}active2{% endifequal %}">{{ city.name }}</span></a>
        {% endfor %}
    </div>

Because city.id is an int type, it needs to be converted into a string and then compared.

 {% ifequal city_id'' %} If it is empty, it means that no city is selected, and "all" is "active"

(2) Category screening

Background processing

     # Category filter
        category = request.GET.get('ct','')
        if category:
            all_orgs = all_orgs.filter(category=category)

        # How many institutions
        org_nums = all_orgs.count()

Put org_numsf at the back, first filter in the statistical quantity

In the template

<h2>Organization category</h2>
    <div class="cont">
        <a href="?city={{ city_id }}"><span
                class="{% ifequal category'' %}active2{% endifequal %}">All</span></a>
        <a href="?ct=pxjg&city={{ city_id }}"><span
                class="{% ifequal category'pxjg' %}active2{% endifequal %}">Training institutions</span></a>
        <a href="?ct=gx&city={{ city_id }}"><span
                class="{% ifequal category'gx' %}active2{% endifequal %}">College</span></a>
        <a href="?ct=gr&city={{ city_id }}"><span
                class="{% ifequal category'gr' %}active2{% endifequal %}">Personal</span></a>
    </div>
<h2>Location</h2>
    <div class="more">More</div>
    <div class="cont">
    <a href="?ct={{ category }}"><span
            class="{% ifequal city_id'' %}active2{% endifequal %}">All</span></a>
    {% for city in all_citys %}
        <a href="?city={{ city.id }}&ct={{ category }}"><span
                class="{% ifequal city_id city.id|stringformat:"i" %}active2{% endifequal %}">{{ city.name }}</span></a>
    {% endfor %}
    </div>

Link cities and classifications:

  • When all categories are selected, only the current city id is passed.
  • When selecting all cities, only the current directory id is passed.
  • Use & connect when both are selected.

(3) Ranking screening of course institutions

 Background processing

 Ranked by clicks, only the first three are taken

# Popular course institution ranking
hot_orgs = all_orgs.order_by('-click_nums')[:3]

In the template

<div class="right companyrank layout">
    <div class="head">Teaching institution ranking</div>
    {% for curent_org in hot_orgs %}
    <dl class="des">
        <dt class="num fl">{{ foorloop.counter }}</dt>
        <dd>
            <a href="/company/2/"><h1>{{ curent_org.name }}</h1></a>
            <p>{{ curent_org.address }}</p>
        </dd>
    </dl>
    {% endfor %}
</div>

When looping, the built-in variable forloop.counter takes the current loop to the number of times

(4) Selection of the number of learners and courses

Add two fields for the number of learners and the number of courses in models

students = models.IntegerField("Number of students",default=0)
course_nums = models.IntegerField("Number of courses",default=0)
class CourseOrg(models.Model):
    ORG_CHOICES = (
        ("pxjg", u"training organization"),
        ("gx", u"high school"),
        ("gr", u"personal"),
    )
    name = models.CharField('Organization Name',max_length=50)
    desc = models.TextField('Organization Description')
    category = models.CharField(max_length=20, choices=ORG_CHOICES, verbose_name=u"organization category", default="pxjg")
    click_nums = models.IntegerField('Number of clicks',default=0)
    fav_nums = models.IntegerField('Number of collections',default=0)
    students = models.IntegerField("Number of students",default=0)
    course_nums = models.IntegerField("Number of courses",default=0)
    image = models.ImageField('logo',upload_to='org/%Y/%m',max_length=100)
    address = models.CharField('Organization address',max_length=150,)
    city ​​= models.ForeignKey(CityDict,verbose_name='City',on_delete=models.CASCADE)
    add_time = models.DateTimeField(default=datetime.now)

    class Meta:
        verbose_name ='Course institution'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name

migrate to the database

Background processing

# Screening of number of learners and number of courses
sort = request.GET.get('sort', "")
if sort:
    if sort == "students":
        all_orgs = all_orgs.order_by("-students")
    elif sort == "courses":
        all_orgs = all_orgs.order_by("-course_nums")
class OrgView(View):
    '''Course institution'''

    def get(self, request):
        # All course institutions
        all_orgs = CourseOrg.objects.all()

        # All cities
        all_citys = CityDict.objects.all()
        # City filter
        city_id = request.GET.get('city','')
        if city_id:
            all_orgs = all_orgs.filter(city_id=int(city_id))

        # Category filter
        category = request.GET.get('ct','')
        if category:
            all_orgs = all_orgs.filter(category=category)

        # Popular course institution ranking
        hot_orgs = all_orgs.order_by('-click_nums')[:3]
        # Screening of number of learners and number of courses
        sort = request.GET.get('sort', "")
        if sort:
            if sort == "students":
                all_orgs = all_orgs.order_by("-students")
            elif sort == "courses":
                all_orgs = all_orgs.order_by("-course_nums")
        # How many institutions
        org_nums = all_orgs.count()
        # Pagination of course institutions
        # Try to get the page parameters passed by the front desk get request
        # If it is an illegal configuration parameter, return to the first page by default
        try:
            page = request.GET.get('page', 1)
        except PageNotAnInteger:
            page = 1
        # Here refers to five from allorg, each page shows five
        p = Paginator(all_orgs, 2, request=request)
        orgs = p.page(page)

        return render(request, "org-list.html", {
            "all_orgs": orgs,
            "all_citys": all_citys,
            "org_nums": org_nums,
            'city_id':city_id,
            "category": category,
            'hot_orgs':hot_orgs,
            'sort':sort,
        })

front end

 <div class="head">
        <ul class="tab_header">
            <li class="{% if sort =='' %}active{% endif %}"><a href="?sort=students&ct={{ category }}&city={{ city_id }}">All</a a></li>
            <li class="{% if sort =='students' %}active{% endif %}"><a href="?sort=students&ct={{ category }}&city={{ city_id }}">Number of students ↓</a></li>
            <li class="{% if sort =='courses' %}active{% endif %}"><a href="?sort=courses&ct={{ category }}&city={{ city_id }}">Number of courses ↓</a></li>
        </ul>
    </div>

7.6. Submit I want to study consultation

(1) Realize with ModelForm

Create the forms.py file in the organazition directory

# organization/forms.py

from django import forms
from operation.models import UserAsk


class UserAskForm(forms.Form):
    '''I want to consult'''
    class Meta:
        model = UserAsk
        fields = ['name','mobile','course_name']

(2) include routing distribution

# MxOnline/urls.py

import xadmin

from django.urls import path,include,re_path

from django.views.generic import TemplateView
from users.views import LoginView,RegisterView,ActiveUserView,ForgetPwdView,ResetView,ModifyPwdView

from organization.views import OrgView
from django.views.static import serve
from MxOnline.settings import MEDIA_ROOT


urlpatterns = [
    path('xadmin/', xadmin.site.urls),
    path('', TemplateView.as_view(template_name='index.html'),name='index'),
    path('login/',LoginView.as_view(),name ='login'),
    path('register/',RegisterView.as_view(),name ='register'),
    path('captcha/',include('captcha.urls')),
    re_path('active/(?P<active_code>.*)/',ActiveUserView.as_view(),name='user_active'),
    path('forget/',ForgetPwdView.as_view(),name='forget_pwd'),
    re_path('reset/(?P<active_code>.*)/', ResetView.as_view(), name='reset_pwd'),
    path('modify_pwd/', ModifyPwdView.as_view(), name='modify_pwd'),

    path('org_list/',OrgView.as_view(),name ='org_list'),
    # Process the url displayed by the picture, use Django's own serve, pass in the parameters to tell it which path to find, we have the configured path MEDIAROOT
    re_path(r'^media/(?P<path>.*)', serve, {"document_root": MEDIA_ROOT }),
]

Delete the route of org_list and change it to include

path("org/", include('organization.urls', namespace="org")),

Use namespaces to prevent duplication

 Then add in organization/urls.py

# organization/urls.py

from organization.views import OrgView

from django.urls import path,re_path

# To write the name of the app
app_name = "organization"

urlpatterns = [
    path('list/',OrgView.as_view(),name='org_list'),
]

Ways of using namespaces in html:

Modify the "link to the course institution" in base.html

<li class="active" ><a href="{% url'org:org_list' %}">Teaching institution</a></li>

(3) View function

from django.http import HttpResponse
from .forms import UserAskForm


class AddUserAskView(View):
    """
    User add consultation
    """
    def post(self, request):
        userask_form = UserAskForm(request.POST)
        if userask_form.is_valid():
            user_ask = userask_form.save(commit=True)
            # If the save is successful, return the json string, and the content type is to tell the browser to return the data type
            return HttpResponse('{"status":"success"}', content_type='application/json')
        else:
            # If the save fails, return the json string, and pass the error message of the form to the front end through msg
            return HttpResponse('{"status":"fail", "msg":"Adding error"}', content_type='application/json')
# organization/views.py

from django.shortcuts import render

from django.views.generic import View
from .models import CourseOrg,CityDict
from pure_pagination import Paginator, EmptyPage, PageNotAnInteger

from django.http import HttpResponse
from .forms import UserAskForm

class OrgView(View):
    '''Course institution'''

    def get(self, request):
        # All course institutions
        all_orgs = CourseOrg.objects.all()

        # All cities
        all_citys = CityDict.objects.all()
        # City filter
        city_id = request.GET.get('city','')
        if city_id:
            all_orgs = all_orgs.filter(city_id=int(city_id))

        # Category filter
        category = request.GET.get('ct','')
        if category:
            all_orgs = all_orgs.filter(category=category)

        # Popular course institution ranking
        hot_orgs = all_orgs.order_by('-click_nums')[:3]
        # Screening of number of learners and number of courses
        sort = request.GET.get('sort', "")
        if sort:
            if sort == "students":
                all_orgs = all_orgs.order_by("-students")
            elif sort == "courses":
                all_orgs = all_orgs.order_by("-course_nums")
        # How many institutions
        org_nums = all_orgs.count()
        # Pagination of course institutions
        # Try to get the page parameters passed by the front desk get request
        # If it is an illegal configuration parameter, return to the first page by default
        try:
            page = request.GET.get('page', 1)
        except PageNotAnInteger:
            page = 1
        # Here refers to five from allorg, each page shows five
        p = Paginator(all_orgs, 2, request=request)
        orgs = p.page(page)

        return render(request, "org-list.html", {
            "all_orgs": orgs,
            "all_citys": all_citys,
            "org_nums": org_nums,
            'city_id':city_id,
            "category": category,
            'hot_orgs':hot_orgs,
            'sort':sort,
        })


class AddUserAskView(View):
    """
    User add consultation
    """
    def post(self, request):
        userask_form = UserAskForm(request.POST)
        if userask_form.is_valid():
            user_ask = userask_form.save(commit=True)
            # If the save is successful, return the json string, and the content type is to tell the browser to return the data type
            return HttpResponse('{"status":"success"}', content_type='application/json')
        else:
            # If the save fails, return the json string, and pass the error message of the form to the front end through msg
            return HttpResponse('{"status":"fail", "msg":"Adding error"}', content_type='application/json')

Ajax submission is used here, the page will not be refreshed as a whole, and a Json data should be returned to the front end

HttpResponse can specify the type of data passed to the front end

(4) Configure url

# organization/urls.py

from organization.views import OrgView,AddUserAskView

from django.urls import path,re_path

# To write the name of the app
app_name = "organization"

urlpatterns = [
    path('list/',OrgView.as_view(),name='org_list'),
    path('add_ask/', AddUserAskView.as_view(), name="add_ask"),
]

(5) Customize a mobile phone number verification method in ModelForm

# organization/forms.py

import re
from django import forms
from operation.models import UserAsk


class UserAskForm(forms.ModelForm):

    class Meta:
        model = UserAsk
        fields = ['name','mobile','course_name']

    def clean_mobile(self):
        """
        Verify that the phone number is legal
        """
        mobile = self.cleaned_data['mobile']
        REGEX_MOBILE = "^1[358]\d{9}$|^147\d{8}$|176\d{8}$"
        p = re.compile(REGEX_MOBILE)
        if p.match(mobile):
            return mobile
        else:
            raise forms.ValidationError(u"Mobile phone number is illegal", code="mobile_invalid")

(6) Submit using Ajax in the template

org-list.html

<div class="right companyright">
    <div class="head">I want to learn</div>
    <form class="rightform" id="jsStayForm">
        <div>
            <img src="{% static'images/rightform1.png' %}"/>
            <input type="text" name="name" id="companyName" placeholder="First name" maxlength="25"/>
        </div>
        <div>
            <img src="{% static'images/rightform2.png' %}"/>
            <input type="text" name="mobile" id="companyMobile" placeholder="Contact number"/>
        </div>
        <div>
            <img src="{% static'images/rightform3.png' %}"/>
            <input type="text" name="course_name" id="companyAddress" placeholder="course name" maxlength="50"/>
        </div>
        <p class="error company-tips" id="jsCompanyTips"></p>
        <input class="btn" type="text" id="jsStayBtn" value="Consult now>"/>
        {% csrf_token %}
    </form>
</div>
<script>
    $(function () {
        $('#jsStayBtn').on('click', function () {
            $.ajax({
                cache: false,
                type: "POST",
                url: "{% url "org:add_ask" %}",
                data: $('#jsStayForm').serialize(),
                async: true,
                success: function (data) {
                    if (data.status =='success') {
                        $('#jsStayForm')[0].reset();
                        alrt("Submitted successfully")
                    } else if (data.status =='fail') {
                        $('#jsCompanyTips').html(data.msg)
                    }
                },
            });
        });
    })
</script>
{#templates/org-list.html#}
{% extends'base.html' %}
{% load staticfiles %}

{% block title %}List of course institutions{% endblock %}


{% block custom_bread %}
    <section>
        <div class="wp">
            <ul class="crumbs">
                <li><a href="index.html">Home</a>></li>
                <li>Course institution</li>
            </ul>
        </div>
    </section>
{% endblock %}


{% block content %}
    <section>
        <div class="wp butler_list_box list">
            <div class='left'>
                <div class="listoptions">
                    <ul>
                        <li>
                            <h2>Organization category</h2>
                            <div class="cont">
                                <a href="?city={{ city_id }}"><span
                                        class="{% ifequal category'' %}active2{% endifequal %}">All</span></a>
                                <a href="?ct=pxjg&city={{ city_id }}"><span
                                        class="{% ifequal category'pxjg' %}active2{% endifequal %}">Training institutions</span></a>
                                <a href="?ct=gx&city={{ city_id }}"><span
                                        class="{% ifequal category'gx' %}active2{% endifequal %}">College</span></a>
                                <a href="?ct=gr&city={{ city_id }}"><span
                                        class="{% ifequal category'gr' %}active2{% endifequal %}">Personal</span></a>
                            </div>
                        </li>
                        <li>
                            <h2>Location</h2>
                            <div class="more">More</div>
                            <div class="cont">
                                <a href="?ct={{ category }}"><span
                                        class="{% ifequal city_id'' %}active2{% endifequal %}">All</span></a>
                                {% for city in all_citys %}
                                    <a href="?city={{ city.id }}&ct={{ category }}"><span
                                            class="{% ifequal city_id city.id|stringformat:"i" %}active2{% endifequal %}">{{ city.name }}</span></a>
                                {% endfor %}
                            </div>
                        </li>
                    </ul>
                </div>

                <div class="all">Total <span class="key">{{ org_nums }}</span>home</div>

                <div class="butler_list company list">
                    <div class="layout">
                        <div class="head">
                            <ul class="tab_header">
                                <li class="{% if sort =='' %}active{% endif %}"><a
                                        href="?sort=students&ct={{ category }}&city={{ city_id }}">All</a></li>
                                <li class="{% if sort =='students' %}active{% endif %}"><a
                                        href="?sort=students&ct={{ category }}&city={{ city_id }}">Number of students↓</a></li>
                                <li class="{% if sort =='courses' %}active{% endif %}"><a
                                        href="?sort=courses&ct={{ category }}&city={{ city_id }}">Number of courses↓</a></li>
                            </ul>
                        </div>


                        {% for course_org in all_orgs.object_list %}
                            <dl class="des difdes">

                                <dt>
                                    <a href="org-detail-homepage.html">

                                        <img width="200" height="120" class="scrollLoading"
                                             data-url="{{ MEDIA_URL }}{{ course_org.image }}"/>

                                    </a>
                                </dt>
                                <dd>
                                    <div class="clearfix">
                                        <a href="org-detail-homepage.html">
                                            <h1>{{ course_org.name }}</h1>
                                            <div class="pic fl">

                                                <img src="{% static'images/authentication.png' %}"/>

                                                <img src="{% static'images/gold.png' %}"/>

                                            </div>
                                        </a>
                                    </div>
                                    <ul class="cont">
                                        <li class="first"><p class="pic9">Number of courses: <span>1</span></p>
                                            <p class="c7">Number of learners: <span>1000</span></p></li>
                                        <li class="c8" style="padding-left:18px;">Zhongguancun North Street, Haidian District, Beijing</li>
                                        <li class="pic10" style="padding-left:18px;">Classic course:

                                            <a href="/diary/19/">c language basics introduction</a>

                                            <a href="/diary/16/">Database Basics</a>

                                        </li>
                                    </ul>
                                </dd>
                                <div class="buy start_groupbuy jsShowPerfect2" data-id="22"><br/>Contact<br/>Services</div>
                            </dl>
                        {% endfor %}


                    </div>
                    <div class="pageturn">
                        <ul class="pagelist">
                            {% if all_orgs.has_previous %}
                                <li class="long"><a href="?{{ all_orgs.previous_page_number.querystring }}">Previous page</a></li>
                            {% endif %}

                            {% for page in all_orgs.pages %}
                                {% if page %}
                                    {% ifequal page all_orgs.number %}
                                        <li class="active"><a href="?{{ page.querystring }}">{{ page }}</a></li>
                                    {% else %}
                                        <li><a href="?{{ page.querystring }}" class="page">{{ page }}</a></li>
                                    {% endifequal %}
                                {% else %}
                                    <li class="none"><a href="">...</a></li>
                                {% endif %}
                            {% endfor %}
                            {% if all_orgs.has_next %}
                                <li class="long"><a href="?{{ all_orgs.next_page_number.querystring }}">Next page</a></li>
                            {% endif %}
                        </ul>
                    </div>

                </div>
            </div>

            <div class="right companyright">
                <div class="head">I want to learn</div>
                <form class="rightform" id="jsStayForm">
                    <div>
                        <img src="{% static'images/rightform1.png' %}"/>
                        <input type="text" name="name" id="companyName" placeholder="First name" maxlength="25"/>
                    </div>
                    <div>
                        <img src="{% static'images/rightform2.png' %}"/>
                        <input type="text" name="mobile" id="companyMobile" placeholder="Contact number"/>
                    </div>
                    <div>
                        <img src="{% static'images/rightform3.png' %}"/>
                        <input type="text" name="course_name" id="companyAddress" placeholder="course name" maxlength="50"/>
                    </div>
                    <p class="error company-tips" id="jsCompanyTips"></p>
                    <input class="btn" type="text" id="jsStayBtn" value="Consult now>"/>
                    {% csrf_token %}
                </form>
            </div>



            <div class="right companyrank layout">
                <div class="head">Teaching institution ranking</div>
                {% for curent_org in hot_orgs %}
                    <dl class="des">
                        <dt class="num fl">{{ foorloop.counter }}</dt>
                        <dd>
                            <a href="/company/2/"><h1>{{ curent_org.name }}</h1></a>
                            <p>{{ curent_org.address }}</p>
                        </dd>
                    </dl>
                {% endfor %}
            </div>
        </div>
    </section>
{% endblock %}


<script>
    $(function () {
        $('#jsStayBtn').on('click', function () {
            $.ajax({
                cache: false,
                type: "POST",
                url: "{% url "org:add_ask" %}",
                data: $('#jsStayForm').serialize(),
                async: true,
                success: function (data) {
                    if (data.status =='success') {
                        $('#jsStayForm')[0].reset();
                        alrt("Submitted successfully")
                    } else if (data.status =='fail') {
                        $('#jsCompanyTips').html(data.msg)
                    }
                },
            });
        });
    })
</script>

When the submitted data is illegal

 When it is legal, a success message will be displayed and the data will be saved to the database

7.7. Organization Homepage

(1) Add a foreign key to courses

from organization.models import CourseOrg

course_org = models.ForeignKey(CourseOrg, on_delete=models.CASCADE, verbose_name="ownership", null=True, blank=True)
# course/models.py

from datetime import datetime

from django.db import models
from organization.models import CourseOrg


class Course(models.Model):
    DEGREE_CHOICES = (
        ("cj", "Beginner"),
        ("zj", "Intermediate"),
        ("gj", "Advanced")
    )
    name = models.CharField("Course Name",max_length=50)
    desc = models.CharField("Course Description", max_length=300)
    detail = models.TextField("Course Details")
    degree = models.CharField('Difficulty',choices=DEGREE_CHOICES, max_length=2)
    learn_times = models.IntegerField("Learning time (minutes)",default=0)
    students = models.IntegerField("Number of students",default=0)
    fav_nums = models.IntegerField("Number of Favorites",default=0)
    image = models.ImageField("Cover image",upload_to="courses/%Y/%m",max_length=100)
    click_nums = models.IntegerField("Number of clicks",default=0)
    add_time = models.DateTimeField("Add Time",default=datetime.now,)
    course_org = models.ForeignKey(CourseOrg, on_delete=models.CASCADE, verbose_name="ownership", null=True, blank=True)

    class Meta:
        verbose_name = "Course"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name

Add courses and lecturers in the background

(2) Template

 Copy the four files of the course organization page to the templates directory

Create a new template, name it "org_base.html", copy the content of org-detail-homepage.html into it

Add block, modify static file path

{#templates/org_base.html#}

{% load staticfiles %}
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
    <title>{% block title %}Organization homepage{% endblock %}</title>
    <link rel="stylesheet" type="text/css" href="{% static'css/reset.css' %}">
    <link rel="stylesheet" type="text/css" href="{% static'css/animate.css' %}">
    <link rel="stylesheet" type="text/css" href="{% static'css/style.css' %}">
    <link rel="stylesheet" type="text/css" href="{% static'js/plugins/queryCity/css/cityLayout.css' %}">
    {% block custom_css %}{% endblock %}
    <script src="{% static'js/jquery.min.js' %}" type="text/javascript"></script>
    <script src="{% static'js/jquery-migrate-1.2.1.min.js' %}" type="text/javascript"></script>
    {% block custom_js %}{% endblock %}
</head>
<body>
<section class="headerwrap headerwrap2">
    <header>
        <div class="header2 header">

                <div class="top">
                <div class="wp">
                    <div class="fl">
                        <p>Contact information: <b>3333333333</b></p>
                    </div>
                    <a style="color:white" class="fr registerbtn" href="register.html">Register</a>
                    <a style="color:white" class="fr loginbtn" href="login.html">Login</a>
                </div>
            </div>


    <div class="middle companyheader">
        <div class="wp">
            <img class="fl" style="width: 112px;height: 103px" src="{% static'media/org/2016/11/imooc.png' %}"/>
            <div class="head fl">
                <h1>
                    MOOC
                    <img src="{% static'images/authentication.png' %}"/>
                    <img src="{% static'images/gold.png' %}"/>
                </h1>
                <p class="fl">
                    <span class="fl" style="margin-top:8px;color:#848484;">Recommendation index: </span>
                    <span class="precision company-credit" data-star-scope="5.0"></span>
                    <span class="key">5.0</span>
                </p>
            </div>
            <div class="btn fr collectionbtn notlogin
                 "data-favid="22" data-fav-type="1">
                 Favorites
            </div>

        </div>
    </div>
            </div>
    </header>
</section>
<section>
    <div class="wp">
        <ul class="crumbs">
            <li><a href="index.html">Home</a>></li>
            <li><a href="org-list.html">Course institutions</a>></li>
            <li>{% block page_path %}Organization homepage{% endblock %}</li>
        </ul>
    </div>
</section>

<section>
    <div class="wp list personal_list comp">
        <div class="left">
            <ul>
                <li class="active2"><a href="org-detail-homepage.html">Organization Homepage</a></li>
                <li class=""><a href="org-detail-course.html">Institutional Courses</a></li>
                <li class=""><a href="org-detail-desc.html">Organization introduction</a></li>
                <li class=""><a href="org-detail-teachers.html">Organization Lecturer</a></li>
            </ul>
        </div>

    {% block right_form %}
    {% endblock %}

    <div class="head">
        <h1>Organization introduction</h1>
        <a class="green fr more" href="org-detail-desc.html">View more> </a>
    </div>
    <div class="cont">    <p>   </p><h1 class="ue_t" label="Title center" name="tc" ​​style="border-bottom-color: #cccccc;border-bottom-width:2px;border-bottom-style:solid;padding:0px 4px 0px 0px;text-align:center;margin:0px 0px 20px;"><span style="color:#c0504d; ">[Type document title]</span></h1><p style="text-align:center;"><strong class="ue_t">[Type document subtitle]</strong></p>< h3><span class="ue_t" style="font-family:幼圆">[Title1]</span></h3><p class="ue_t" style="text-indent:2em;"> For the library on the "Insert" tab, the items in it and the overall appearance of the document are coordinated in design. You can use these libraries to insert tables, headers, footers, lists, covers, and other document building blocks. The pictures, diagrams, or diagrams you create will also be consistent with the appearance of the current document. </p><p class="ue_t" style="text-indent:2em;"><img src="../media/courses/ueditor/57aa86a0000145c512000460_20161210234050_865.jpg" title="" alt="57aa86a0000145c512000460.jpg"/> </p><h3>< span class="ue_t" style="font-family:幼圆">[title 2]</span></h3><p><img src="http://api.map.baidu.com/staticimage ?center=116.410899,39.863624&zoom=11&width=530&height=340&markers=116.404,39.915" width="530" height="340"/> </p><p class="ue_t" style="text-indent:2em; ">On the "Home" tab, you can easily change the format of the selected text in the document by choosing a look for the selected text from the quick style library. You can also use other controls on the Start tab to directly format text. Most controls allow you to choose whether to use the current theme appearance or a directly specified format. </p><h3><span class="ue_t" style="font-family:幼圆">[Title 3]</span></h3><p> 2016-12-10</p><p class="ue_t">For the library on the "Insert" tab, the design has fully considered the coordination between the items and the overall appearance of the document. You can use these libraries to insert tables, headers, footers, lists, covers, and other document building blocks. The pictures, diagrams, or diagrams you create will also be consistent with the appearance of the current document. </p><p class="ue_t"><br/> </p><p><br/></p><p><br/></p><a href="/company/desc/22/"><span class="green">[see more]</span></a></div>
</div>


</section>
<!--sidebar start-->
<section>
    <ul class="sidebar">
        <li class="qq">
            <a target="_blank" href="http://wpa.qq.com/msgrd?v=3&uin=2023525077&site=qq&menu=yes"></a>
        </li>
        <li class="totop"></li>
    </ul>
</section>
<!--sidebar end-->
<!--header start-->
</div>
<!--Pop up provinces and cities-->
<script src="{% static'js/selectUi.js' %}" type='text/javascript'></script>
<script type="text/javascript" src="{% static'js/plugins/laydate/laydate.js' %}"></script>
<script src="{% static'js/plugins/layer/layer.js' %}"></script>
<script src="{% static'js/plugins/queryCity/js/public.js' %}" type="text/javascript"></script>

<script type="text/javascript" src="{% static'js/plugins/jquery.raty.js' %}"></script>
<script type="text/javascript">
   //Favorite sharing
//Favorite sharing
function add_fav(current_elem, fav_id, fav_type){
    $.ajax({
        cache: false,
        type: "POST",
        url:"/org/add_fav/",
        data:{'fav_id':fav_id,'fav_type':fav_type},
        async: true,
        beforeSend:function(xhr, settings){
            xhr.setRequestHeader("X-CSRFToken", "5I2SlleZJOMUX9QbwYLUIAOshdrdpRcy");
        },
        success: function(data) {
            if(data.status =='fail'){
                if(data.msg =='User is not logged in'){
                    win.loc.href="login.html";
                }else{
                    alrt(data.msg)
                }

            }else if(data.status =='success'){
                current_elem.text(data.msg)
            }
        },
    });
}

$('.collectionbtn').on('click', function(){
    add_fav($(this), 1, 2);
});

$(function(){
    var $precision = $('.precision'),
        score = $precision.attr('data-star-scope'),
        option = {
                    half: true,
                    path:'../images/',
                    precision: true,
                    size: 24,
                    starOff:'g_star.png',
                    starOn:'r_star.png',
                    starHalf:'h_star.png',
                    hints: ['very bad','bad','average','good comment','very satisfied'],
                    noRatedMsg: "I have not yet received reviews yet! ',
                    readOnly: true,
                    score: score
                };
    $precision.raty(option);

    $('.jsFavBtn').on('click', function(){
        var type = $(this).attr('data-fav-type');
        if(type == '1'){
            favPraise($(this),'fav' ,1,'collection');

        }else if(type == '3'){
            favPraise($(this),'fav' ,3 );

        }else if(type == '11'){
            favPraise($(this),'pra', 1);

        }else if(type == '4'){
            favPraise($(this),'fav' ,4 );

        }
    });
})
</script>


<script type="text/javascript">
$(function() {
    $('.recordbtn1').click(function(){
        $('.recordbox1').show();
    });
    $('.recordbtn2').click(function(){
        $('.recordbox2').show();
    });

    $('.imgslide').unslider({
        speed: 500,//The speed to animate each slide (in milliseconds)
        delay: 3000,//The delay between slide animations (in milliseconds)
        complete: function() {},//A function that gets called after every slide animation
        keys: true,//Enable keyboard (left, right) arrow shortcuts
        dots: true,//Display dot navigation
        fluid: false//Support responsive design. May break non-responsive designs
    });
    var unslider = $('.imgslide').unslider();
    $('.unslider-arrow').click(function() {
        var fn = this.className.split('')[1];
        unslider.data('unslider')[fn]();
    });
});
</script>

</body>
</html>

(3) org-detail-home.html inherited template

Cut the three "rights" in org_base into home

(4) The url of the home page

from .views import OrgHomeView

re_path('home/(?P<org_id>\d+)/', OrgHomeView.as_view(), name="org_home"),

(5) Back-end logic processing

class OrgHomeView(View):
    '''Organization Homepage'''

    def get(self,request,org_id):
        # Find course institution according to id
        course_org = CourseOrg.objects.get(id=int(org_id))
        # Reverse query to all courses and teachers of the course institution
        all_courses = course_org.course_set.all()[:4]
        all_teacher = course_org.teacher_set.all()[:2]
        return render(request,'org-detail-homepage.html',{
            'course_org':course_org,
            'all_courses':all_courses,
            'all_teacher':all_teacher,
        })

(6) Show all courses

<div class="brief group_list">
        {% for course in all_courses %}
         <div class="module1_5 box">
            <a href="course-detail.html"><img width="214" src="{{ MEDIA_URL }}{{ course.image }}"/></a>
            <div class="des">
                <a href="course-detail.html"><h2>{{ course.name }}</h2></a>
                <span class="fl">Class hours: <i class="key">{{ course.learn_times }}</i></span>
                <span class="fr">Number of participants: {{ course.students }}</span>
            </div>
            <div class="bottom">
                <span class="fl">{{ course.course_org.name }}</span>
                 <span class="star fr notlogin
                    "data-favid="13" data-fav-type="4">
                    {{ course.fav_nums }}
                </span>
            </div>
        </div>
        {% endfor %}
</div>

Modify the link in org-list.html and click on the organization to jump to the homepage of the corresponding organization

(6) Modify org-base.html

 (7) Add a graphic field for the teacher

image = models.ImageField(
    default='',
    upload_to="teacher/%Y/%m",
    verbose_name="avatar",
    max_length=100)

(8) Display institution teachers

 (9) Display organization details

Organization Homepage:

7.8. Institutional courses

 (1) Template file

Take out the different places (right) in org-detail-course.html

(2) Add url

re_path('course/(?P<org_id>\d+)/', OrgCourseView.as_view(), name="org_course"),

(3) views.py

class OrgCourseView(View):
    """
   Institutional Course List Page
    """
    def get(self, request, org_id):
        # Get the course institution according to id
        course_org = CourseOrg.objects.get(id = int(org_id))
        # Find courses by course organization. Built-in variable, find the foreign key reference pointing to this field
        all_courses = course_org.course_set.all()

        return render(request,'org-detail-course.html',{
           'all_courses':all_courses,
            'course_org': course_org,
        })

(4) Modify the link left in org-base.html

 (5) Display institution courses, modify org-detail-course.html

<div class="brief group_list">
{% for course in all_courses %}
    <div class="module1_5 box">
        <a class="comp-img-box" href="course-detail.html">

            <img width="214" height="195" src="{{ MEDIA_URL }}{{ course.image }}"/>
        </a>
        <div class="des">
            <a href="course-detail.html"><h2>{{ course.name }}</h2></a>
            <span class="fl">Class hours: <i class="key">{{ course.learn_times }}</i></span>
            <span class="fr">Number of students{{ course.students }}</span>
        </div>
        <div class="bottom">
            <span class="fl">{{ course.course_org.name }}</span>
            <span class="star fr notlogin
                "data-favid="13" data-fav-type="4">
                {{ course.fav_nums }}
            </span>
        </div>
    </div>
{% endfor %}

Click "Institutional Courses" to see which courses are available

(6) Modification of the "active" status on the left

Because there is no value to determine which page is currently. So pass a current page parameter in the background

 Modify org_base.html

<div class="left">
    <ul>
        <li class="{% ifequal current_page'home' %}active2{% endifequal %}"><a href="{% url'org:org_home' course_org.id %}">Organization homepage</a></a></a> li>
        <li class="{% ifequal current_page'course' %}active2{% endifequal %}"><a href="{% url'org:org_course' course_org.id %}">Institutional courses</a></a></a> li>
        <li class="{% ifequal current_page'desc' %}active2{% endifequal %}"><a href="org-detail-desc.html">Organization introduction</a></li>
        <li class="{% ifequal current_page'teacher' %}active2{% endifequal %}"><a href="org-detail-teachers.html">Organization Lecturer</a></li>
    </ul>
</div>

Modify the views and pass a current_page parameter to the front end to know which is currently activated

class OrgHomeView(View):
    '''Organization Homepage'''

    def get(self,request,org_id):
        current_page ='home'
        # Find course institution according to id
        course_org = CourseOrg.objects.get(id=int(org_id))
        # Reverse query to all courses and teachers of the course institution
        all_courses = course_org.course_set.all()[:4]
        all_teacher = course_org.teacher_set.all()[:2]
        return render(request,'org-detail-homepage.html',{
            'course_org':course_org,
            'all_courses':all_courses,
            'all_teacher':all_teacher,
            'current_page':current_page,
        })
class OrgCourseView(View):
    """
   Institutional Course List Page
    """
    def get(self, request, org_id):
        current_page ='course'
        # Get the course institution according to id
        course_org = CourseOrg.objects.get(id = int(org_id))
        # Find courses by course organization. Built-in variable, find the foreign key reference pointing to this field
        all_courses = course_org.course_set.all()

        return render(request,'org-detail-course.html',{
           'all_courses':all_courses,
            'course_org': course_org,
            'current_page':current_page,
        })

 7.9. Institutional introduction

(1) url

re_path('desc/(?P<org_id>\d+)/', OrgDescView.as_view(), name="org_desc"),

 (2) views

class OrgDescView(View):
    '''Organization Introduction Page'''
    def get(self, request, org_id):
        current_page ='desc'
        # Get the course institution according to id
        course_org = CourseOrg.objects.get(id = int(org_id))
        return render(request,'org-detail-desc.html',{
            'course_org': course_org,
            'current_page':current_page,
        })

7.10. Institutional Lecturer

(1) url

re_path('teacher/(?P<org_id>\d+)/', OrgTeacherView.as_view(), name="org_teacher"),

(2) views

class OrgTeacherView(View):
    """
   Institutional Teacher Page
    """
    def get(self, request, org_id):
        current_page ='teacher'
        course_org = CourseOrg.objects.get(id = int(org_id))
        all_teacher = course_org.teacher_set.all()

        return render(request,'org-detail-teachers.html',{
           'all_teacher':all_teacher,
            'course_org': course_org,
            'current_page':current_page,
        })

(3) org-detail-teachers.html

{% extends'org_base.html' %}
{% load staticfiles %}

<title>{% block title %}Organization Teacher Page--New Oriental {% endblock %}</title>

{% block right_form %}
 <div class="right companycenter layout">
        <div class="head">
            <h1>Institutional Lecturer</h1>
        </div>
        <div class="messagelist">
            <div class=" butler_list butler-fav-box">
                {% for teacher in all_teacher %}
                <dl class="des users">
                    <dt>
                        <a href="">
                        <img width="100" height="100" class="scrollLoading" data-url="{{ MEDIA_URL }}{{ teacher.image }}" src="{{ MEDIA_URL }}{{ teacher.image }} "/>
                        </a>
                    </dt>
                    <dd>
                        <h1>
                            <a href="">
                            {{ teacher.name }}<span class="key">Certified</span>
                            </a>
                        </h1>
                        <ul class="cont clearfix">
                            <li class="time">Work years: <span>{{ teacher.work_years }}</span></li>
                            <li class="c7">Number of courses: <span>3</span></li>
                        </ul>
                    </dd>
                </dl>
                {% endfor %}
            </div>
        </div>
    </div>
{% endblock %}

 (4) Left in org-bae.html

<ul>
   <li class="{% ifequal current_page'home' %}active2{% endifequal %}"><a href="{% url'org:org_home' course_org.id %}">Organization homepage</a></a></a> li>
   <li class="{% ifequal current_page'course' %}active2{% endifequal %}"><a href="{% url'org:org_course' course_org.id %}">Institutional courses</a></a></a> li>
   <li class="{% ifequal current_page'desc' %}active2{% endifequal %}"><a href="{% url'org:org_desc' course_org.id %}">Introduction to institution</a></a></a> li>
   <li class="{% ifequal current_page'teacher' %}active2{% endifequal %}"><a href="{% url'org:org_teacher' course_org.id %}">Institutional lecturer</a></a></a> li>
</ul>

 (5) Modify the breadcrumbs, and click Institutional Courses should display Institutional Courses

base.html

 Then reload page_path in the other four pages respectively

The other three methods are the same

7.11. Curriculum institution collection function

 (1) url

path('add_fav/', AddFavView.as_view(), name="add_fav"),
# organization/urls.py

from organization.views import OrgView,AddUserAskView

from django.urls import path,re_path
from .views import OrgHomeView,OrgCourseView,OrgDescView,OrgTeacherView,AddFavView

# To write the name of the app
app_name = "organization"

urlpatterns = [
    path('list/',OrgView.as_view(),name='org_list'),
    path('add_ask/', AddUserAskView.as_view(), name="add_ask"),
    re_path('home/(?P<org_id>\d+)/', OrgHomeView.as_view(), name="org_home"),
    re_path('course/(?P<org_id>\d+)/', OrgCourseView.as_view(), name="org_course"),
    re_path('desc/(?P<org_id>\d+)/', OrgDescView.as_view(), name="org_desc"),
    re_path('teacher/(?P<org_id>\d+)/', OrgTeacherView.as_view(), name="org_teacher"),
    path('add_fav/', AddFavView.as_view(), name="add_fav"),
]
# MxOnline/urls.py

import xadmin

from django.urls import path,include,re_path

from django.views.generic import TemplateView
from users.views import LoginView,RegisterView,ActiveUserView,ForgetPwdView,ResetView,ModifyPwdView
from organization.views import OrgView
from django.views.static import serve
from MxOnline.settings import MEDIA_ROOT


urlpatterns = [
    path('xadmin/', xadmin.site.urls),
    path('', TemplateView.as_view(template_name='index.html'),name='index'),
    path('login/',LoginView.as_view(),name ='login'),
    path('register/',RegisterView.as_view(),name ='register'),
    path('captcha/',include('captcha.urls')),
    re_path('active/(?P<active_code>.*)/',ActiveUserView.as_view(),name='user_active'),
    path('forget/',ForgetPwdView.as_view(),name='forget_pwd'),
    re_path('reset/(?P<active_code>.*)/', ResetView.as_view(), name='reset_pwd'),
    path('modify_pwd/', ModifyPwdView.as_view(), name='modify_pwd'),

    path("org/", include('organization.urls', namespace="org")),
    # Process the url displayed by the picture, use Django's own serve, pass in the parameters to tell it which path to find, we have the configured path MEDIAROOT
    re_path(r'^media/(?P<path>.*)', serve, {"document_root": MEDIA_ROOT }),
]

(2) Background processing

class AddFavView(View):
    """
    User favorites and unfavorites
    """
    def post(self, request):
        fav_id = request.POST.get('fav_id', 0) # Prevent errors in the back int(fav_id)
        fav_type = request.POST.get('fav_type', 0) # Prevent int(fav_type) error

        if not request.user.is_authenticated:
            # When you are not logged in, return json to prompt you are not logged in. Jumping to the login page is done in ajax
            return HttpResponse('{"status":"fail", "msg":"User not logged in"}', content_type='application/json')

        exist_record = UserFavorite.objects.filter(user=request.user, fav_id=int(fav_id), fav_type=int(fav_type))
        if exist_record:
            # If the record already exists, it means that the user unfavored
            exist_record.delete()
            return HttpResponse('{"status":"fail", "msg":"Uncollected"}', content_type='application/json')
        else:
            user_fav = UserFavorite()
            if int(fav_id)> 0 and int(fav_type)> 0:
                user_fav.user = request.user
                user_fav.fav_id = int(fav_id)
                user_fav.fav_type = int(fav_type)
                user_fav.save()
                return HttpResponse('{"status":"success", "msg":"Collection"}', content_type='application/json')
            else:
                return HttpResponse('{"status":"fail", "msg":"Collection error"}', content_type='application/json')

(3) Front-end Ajax

Ajax is placed in org_base.html

<script type="text/javascript">
   //Favorite sharing
//Favorite sharing
function add_fav(current_elem, fav_id, fav_type){
    $.ajax({
        cache: false,
        type: "POST",
        url:"{% url'org:add_fav' %}",
        data:{'fav_id':fav_id,'fav_type':fav_type},
        async: true,
        beforeSend:function(xhr, settings){
            xhr.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
        },
        success: function(data) {
            if(data.status =='fail'){
                if(data.msg =='User is not logged in'){
                    win.loc.href="/login/";
                }else{
                    alrt(data.msg)
                }

            }else if(data.status =='success'){
                current_elem.text(data.msg)
            }
        },
    });
}

$('.collectionbtn').on('click', function(){
    add_fav($(this), {{ course_org.id }}, 2);
});

Visit the page and click "Favorites" in the upper right corner, you can find that it works normally

You can see the user's favorites in the database

Click "Favorite" again, it will prompt "Unfavorite"

(4) But there is another problem. After refreshing the page, "Favorite" becomes "Favorite" because when returning to the page, the status of the collection is not judged.

All you need to add a judgment in the views

        # Determine the status of the collection
        has_fav = False
        if request.user.is_authenticated:
            if UserFavorite.objects.filter(user=request.user, fav_id=course_org.id, fav_type=2):
                has_fav = True

Add this judgment on all four pages

# organization/views.py

from django.shortcuts import render

from django.views.generic import View
from .models import CourseOrg,CityDict
from pure_pagination import Paginator, EmptyPage, PageNotAnInteger

from django.http import HttpResponse
from .forms import UserAskForm
from operation.models import UserFavorite
from django.contrib.auth import authenticate

class OrgView(View):
    '''Course institution'''

    def get(self, request):
        # All course institutions
        all_orgs = CourseOrg.objects.all()

        # All cities
        all_citys = CityDict.objects.all()
        # City filter
        city_id = request.GET.get('city','')
        if city_id:
            all_orgs = all_orgs.filter(city_id=int(city_id))

        # Category filter
        category = request.GET.get('ct','')
        if category:
            all_orgs = all_orgs.filter(category=category)

        # Popular course institution ranking
        hot_orgs = all_orgs.order_by('-click_nums')[:3]
        # Screening of number of learners and number of courses
        sort = request.GET.get('sort', "")
        if sort:
            if sort == "students":
                all_orgs = all_orgs.order_by("-students")
            elif sort == "courses":
                all_orgs = all_orgs.order_by("-course_nums")
        # How many institutions
        org_nums = all_orgs.count()
        # Pagination of course institutions
        # Try to get the page parameters passed by the front desk get request
        # If it is an illegal configuration parameter, return to the first page by default
        try:
            page = request.GET.get('page', 1)
        except PageNotAnInteger:
            page = 1
        # Here refers to five from allorg, each page shows five
        p = Paginator(all_orgs, 2, request=request)
        orgs = p.page(page)

        return render(request, "org-list.html", {
            "all_orgs": orgs,
            "all_citys": all_citys,
            "org_nums": org_nums,
            'city_id':city_id,
            "category": category,
            'hot_orgs':hot_orgs,
            'sort':sort,
        })


class AddUserAskView(View):
    """
    User add consultation
    """
    def post(self, request):
        userask_form = UserAskForm(request.POST)
        if userask_form.is_valid():
            user_ask = userask_form.save(commit=True)
            # If the save is successful, return the json string, and the content type is to tell the browser to return the data type
            return HttpResponse('{"status":"success"}', content_type='application/json')
        else:
            # If the save fails, return the json string, and pass the error message of the form to the front end through msg
            return HttpResponse('{"status":"fail", "msg":"Adding error"}', content_type='application/json')


class OrgHomeView(View):
    '''Organization Homepage'''

    def get(self,request,org_id):
        current_page ='home'
        # Find course institution according to id
        course_org = CourseOrg.objects.get(id=int(org_id))
        # Judging the collection status
        has_fav = False
        if request.user.is_authenticated:
            if UserFavorite.objects.filter(user=request.user, fav_id=course_org.id, fav_type=2):
                has_fav = True
        # Reverse query to all courses and teachers of the course institution
        all_courses = course_org.course_set.all()[:4]
        all_teacher = course_org.teacher_set.all()[:2]
        return render(request,'org-detail-homepage.html',{
            'course_org':course_org,
            'all_courses':all_courses,
            'all_teacher':all_teacher,
            'current_page':current_page,
            'has_fav': has_fav,
        })

class OrgCourseView(View):
    """
   Institutional Course List Page
    """
    def get(self, request, org_id):
        current_page ='course'
        # Get the course institution according to id
        course_org = CourseOrg.objects.get(id = int(org_id))
        # Find courses by course organization. Built-in variable, find the foreign key reference pointing to this field
        all_courses = course_org.course_set.all()
        # Judging the collection status
        has_fav = False
        if request.user.is_authenticated:
            if UserFavorite.objects.filter(user=request.user, fav_id=course_org.id, fav_type=2):
                has_fav = True

        return render(request,'org-detail-course.html',{
           'all_courses':all_courses,
            'course_org': course_org,
            'current_page':current_page,
            'has_fav': has_fav,
        })


class OrgDescView(View):
    '''Organization Introduction Page'''
    def get(self, request, org_id):
        current_page ='desc'
        # Get the course institution according to id
        course_org = CourseOrg.objects.get(id = int(org_id))
        # Judging the collection status
        has_fav = False
        if request.user.is_authenticated:
            if UserFavorite.objects.filter(user=request.user, fav_id=course_org.id, fav_type=2):
                has_fav = True
        return render(request,'org-detail-desc.html',{
            'course_org': course_org,
            'current_page':current_page,
            'has_fav': has_fav,
        })

class OrgTeacherView(View):
    """
   Institutional Teacher Page
    """
    def get(self, request, org_id):
        current_page ='teacher'
        course_org = CourseOrg.objects.get(id = int(org_id))
        all_teacher = course_org.teacher_set.all()
        # Judging the collection status
        has_fav = False
        if request.user.is_authenticated:
            if UserFavorite.objects.filter(user=request.user, fav_id=course_org.id, fav_type=2):
                has_fav = True

        return render(request,'org-detail-teachers.html',{
           'all_teacher':all_teacher,
            'course_org': course_org,
            'current_page':current_page,
            'has_fav': has_fav,
        })

class AddFavView(View):
    """
    User favorites and unfavorites
    """
    def post(self, request):
        fav_id = request.POST.get('fav_id', 0) # Prevent errors in the back int(fav_id)
        fav_type = request.POST.get('fav_type', 0) # Prevent int(fav_type) error

        if not request.user.is_authenticated:
            # When you are not logged in, return json to prompt you are not logged in. Jumping to the login page is done in ajax
            return HttpResponse('{"status":"fail", "msg":"User not logged in"}', content_type='application/json')

        exist_record = UserFavorite.objects.filter(user=request.user, fav_id=int(fav_id), fav_type=int(fav_type))
        if exist_record:
            # If the record already exists, it means that the user unfavored
            exist_record.delete()
            return HttpResponse('{"status":"fail", "msg":"Uncollected"}', content_type='application/json')
        else:
            user_fav = UserFavorite()
            if int(fav_id)> 0 and int(fav_type)> 0:
                user_fav.user = request.user
                user_fav.fav_id = int(fav_id)
                user_fav.fav_type = int(fav_type)
                user_fav.save()
                return HttpResponse('{"status":"success", "msg":"Collection"}', content_type='application/json')
            else:
                return HttpResponse('{"status":"fail", "msg":"Collection error"}', content_type='application/json')

(5) Add judgment in org_base.html

 (6) Modify the login and registration in the upper right corner

Put the login and registration judgments in the index.html page into org_base

Reference: https://cloud.tencent.com/developer/article/1091398 Django+xadmin to build an online education platform (4)-Cloud + Community-Tencent Cloud