Django 自关联之 - 地址省市区

创建一个新的模块应用areas

在这里插入图片描述
指令:

python ../../manage.py startapp areas

在配置文件,添加路径:

INSTALLED_APPS = [
    'areas.apps.AreasConfig',
]

models.py 文件创建数据表:

from django.db import models

# Create your models here.

class Areas(models.Model):

    name = models.CharField(max_length=50, verbose_name='地名')
    pid = models.ForeignKey('self', on_delete=models.SET_NULL, related_name='addinfo', null=True, blank=True, verbose_name='上一级别的行政区的id')

    # on_delete = models.CASCADE # 删除关联数据的时候,与之相关联的也删除
    # on_delete = models.DO_NOTHING # ... , 什么操作也不做
    # on_delete = models.PROTECT # ... ,引发报错
    # on_delete = models.SET_NULL # ... ,设置为空
    # on_delete = models.SET_DEFAULT # ... , 设置为默认值
    # on_delete = models.SET # ... , 删除关联数据

    class Meta:
        db_table = 'areas'

    def __str__(self):
        return self.name

说明:

  • name 是省市区的名字
  • pid 外键,self 自相关,这里也可以使用Areas。
  • related_name=’addinfo’ ,相当于一对多的类型,子表的名字,可以通过areas.addinfo.all() 来获取子表的所有信息。
  • null 为True表示可为空,因为省级行政单位没有父级
  • blank 为True 表示在admin后台调试数据库的时候可以允许为空

迁移数据库

每当对models模型进行修改时,都要记得迁移数据库

python manage.py makemigrations
python manage.py migrate

然后下载数据库文件areas.sql ,然后在文件对应的路径导入到数据库中

mysql -uroot -p shanghui < areas.sql

areas.sql 部分内容:
在这里插入图片描述

新建一个serializers.py文件写序列化器类

from rest_framework import serializers
from . import models

# 这个序列化器就是展示地区名
class AreaInfoSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Areas
        fields = ('id', 'name',)

# 这个序列器展示他的下一级地区名
class NextAreaInfoSerializer(serializers.ModelSerializer):
    # 嵌套关系
    addinfo = AreaInfoSerializer(many=True, read_only=True)
	# 注意 这里的    addinfo 要和 上面 models.py 文件里的related_name 名字相对应

	# addinfo = serializers.StringRelatedField(many=True, read_only=True)
	# 这个是返回字符串显示的是__str__方法返回的内容。

	# 上面什么都不写,也就是只有下面Meta类的时候,默认是PrimaryKeyrelatedField,也就是显示id

    #  显示下一级的内容
    class Meta:
        model = models.Areas
        fields = ('id', 'name', 'addinfo', )

views.py 文件编写:

这里使用ReadOnlyModelViewSet,因为能根据不同的请求指定不同的序列化器

from django.shortcuts import render
from rest_framework.viewsets import ReadOnlyModelViewSet

from . import models
from . import serializers
# Create your views here.


class AreasView(ReadOnlyModelViewSet):

    def get_queryset(self):
        if self.action == 'list':
            # pid = None 的时候,返回的是省级数据
            return models.Areas.objects.filter(pid=None)
        else:
            return models.Areas.objects.all()

    def get_serializer_class(self):
        if self.action == 'list':
            return serializers.AreaInfoSerializer
        else:
            return serializers.NextAreaInfoSerializer

在urls文件配置路由器

在使用viewsets类的时候,一般都是使用路由器自动配置路径

from django.conf.urls import url
from rest_framework import routers
from . import views


router = routers.DefaultRouter()# 默认附带一个api根式图,相对于SimpleRouter()来说
# router = routers.SimpleRouter()

router.register(r'areas', views.AreasView, base_name='areas')


urlpatterns = [

]

urlpatterns += router.urls

通过接口文档查看效果

在这里插入图片描述

扫描二维码关注公众号,回复: 6727346 查看本文章

在这里插入图片描述
在这里插入图片描述

前端js文件代码:

主要使用到的是jQuery 里面的change事件。

    // 地址 省 下拉菜单
    $.ajax({
        url:'http://127.0.0.1:8000/areas/areas',
        type:'GET',
        dataType:'json',
        contentType: 'application/json',
        success:function (data) {

            console.log(data.length);

            var newdata = '<option value="1">' + '省' + '</option>';
            for(var i=0;i<data.length;i++){
                newdata += '<option value =' + data[i]["id"] + '>' + data[i]['name'] + '</option>'
            }
            $('#addprovince').html(newdata);
        },
        error:function (data) {
            console.log(data);
        }
    });
    // 地址 市 下拉菜单
    $('#addprovince').change(function () {
        var data_id = $(this).val();
        $.ajax({
            url:'http://127.0.0.1:8000/areas/areas/'+ data_id + '/',
            type:'GET',
            success:function (data) {
                var city_data = '';
                for(var i=0;i<data['addinfo'].length; i++) {
                    // console.log(data['addinfo'][i]);
                    city_data += '<option value =' + data['addinfo'][i]["id"] + '>' + data['addinfo'][i]['name'] + '</option>'
                }
                $('#addcity').html(city_data);
                var city_length =  $('#addcity').children().length;
                // console.log('个数',city_length);
                if (city_length ==1){
                    // var district = '<option value="3">' + '/' + '</option>';
                    var district = $('#addcity').html();
                    $('#adddistrict').html(district);
                }
            },
            error:function (data) {
                console.log(data);
            }
        })
    });
    // 地址 区 下拉菜单
    $('#addcity').change(function () {
        var data_id = $(this).val();
        $.ajax({
            url:'http://127.0.0.1:8000/areas/areas/'+ data_id + '/',
            type:'GET',
            success:function (data) {
                // console.log(data);
                var district_data = '';
                for(var i=0;i<data['addinfo'].length; i++) {
                    // console.log(data['addinfo'][i]);
                    district_data += '<option value =' + data['addinfo'][i]["id"] + '>' + data['addinfo'][i]['name'] + '</option>'
                }
                $('#adddistrict').html(district_data);
            },
            error:function (data) {
                console.log(data);
            }
        })
    });

猜你喜欢

转载自blog.csdn.net/dakengbi/article/details/93199148