zoukankan      html  css  js  c++  java
  • Django Admin 实现三级联动的示例代码(省市区)===>小白级

    一  使用环境

      开发系统: windows

      IDE: pycharm  

      数据库: msyql,navicat

      编程语言: python3.7  (Windows x86-64 executable installer)

      虚拟环境: virtualenvwrapper

      开发框架: Django 2.2

      Django 2.2通病===>访问admin出现问题:

      报错:UnicodeDecodeError: 'gbk' codec can't decode byte 0xa6 in position 9737: illegal multibyte sequence

      解决方法:https://www.cnblogs.com/djtang/p/10194811.html

    二 Django Admin 实现三级联动的示例代码(省市区)===>小白级

    1. 在 model.py 中

    from django.db import models
    
    
    # 人员
    class Member(models.Model):
        name = models.CharField(max_length=100, verbose_name='姓名')
        province = models.ForeignKey('Province', on_delete=models.PROTECT, null=True, blank=True, verbose_name='省份')
        city = models.ForeignKey('City', on_delete=models.PROTECT, null=True, blank=True, verbose_name='城市')
        district = models.ForeignKey('District', on_delete=models.PROTECT, null=True, blank=True, verbose_name='区/县')
    
        class Meta:
            verbose_name_plural = verbose_name = '00-人员'
    
        def __str__(self):
            return self.name
    
    
    # 省份
    class Province(models.Model):
        省份 = models.CharField(max_length=100, null=True, blank=True, verbose_name='省份')
    
        class Meta:
            verbose_name_plural = verbose_name = '01-省份'
    
        def __str__(self):
            return self.省份
    
    
    # 城市
    class City(models.Model):
        城市 = models.CharField(max_length=100, null=True, blank=True, verbose_name='城市')
        省份 = models.ForeignKey('Province', on_delete=models.PROTECT, null=True, blank=True, related_name='城市_省份',
                               verbose_name='省份')
    
        class Meta:
            verbose_name_plural = verbose_name = '02-城市'
    
        def __str__(self):
            return self.城市
    
    
    # 区/县
    class District(models.Model):
        区县 = models.CharField(max_length=100, null=True, blank=True, verbose_name='区/县')
        城市 = models.ForeignKey('City', on_delete=models.PROTECT, null=True, blank=True, related_name='区县_城市',
                               verbose_name='城市')
    
        class Meta:
            verbose_name_plural = verbose_name = '03-区/县'
    
        def __str__(self):
            return self.区县

    2. 在 view.py 中

    from django.http import JsonResponse
    from sjld.models import Province, City, District
    
    
    # Create your views here.
    
    # 省份
    def choose_province(request):
        省份 = Province.objects.all()
        result = []
        for i in 省份:
            result.append(i.省份)  # 取公司的简称
        province = result  # 传递一个列表
        return JsonResponse(province, safe=False)
    
    
    def choose_city(request):
        省份 = request.GET.get('p')  # 取上面选中省份的名称
        城市 = City.objects.all()
        result = []
        for i in 城市:
            if str(省份) == str(i.省份):
                result.append(i.城市)
        cities = result  # 传递一个列表
        return JsonResponse(cities, safe=False)
    
    
    def choose_district(request):
        城市 = request.GET.get('c')  # 取上面选中城市的名称
        区县 = District.objects.all()
        result = []
        for i in 区县:
            if str(城市) == str(i.城市):
                result.append(i.区县)
        cities = result  # 传递一个列表
        districts = cities
        return JsonResponse(districts, safe=False)

    3. 在 urls.py 中

    from django.contrib import admin
    from django.urls import path
    from sjld.views import choose_province, choose_city, choose_district
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('province/', choose_province),
        path('city/', choose_city),
        path('district/', choose_district),
    ]

    4. 在 admin.py 中 

    from django import forms
    from django.contrib import admin
    from shanjld.models import Member, Province, City, District
    
    
    class MemberForm(forms.ModelForm):
        class Meta:
            widgets = {
                'province': forms.Select(),
                'city': forms.Select(),
                'district': forms.Select()
            }
    
    
    # 人员
    @admin.register(Member)
    class MemberAdmin(admin.ModelAdmin):
        form = MemberForm
        change_form_template = 'area.html'
        # raw_id_fields = ('province', 'city', 'district',)  # 这个在这里就无效了,希望哪位大老指点一下,怎么重写这个方法.
        fields = ('name', 'province', 'city', 'district')
        list_display = ('name', 'province', 'city', 'district')
    
    
    # 省份
    @admin.register(Province)
    class ProvinceAdmin(admin.ModelAdmin):
        pass
    
    
    # 城市
    @admin.register(City)
    class CityAdmin(admin.ModelAdmin):
        raw_id_fields = ('省份',)
    
    
    # 区/县
    @admin.register(District)
    class DistrictAdmin(admin.ModelAdmin):
        raw_id_fields = ('城市',)

    5. 在项目 templates 文件下新建一个 area.html 文件

    6. 找到django源码中的 change_form.html 文件,打开复制里面全部的html内容到 area.html 中. (文件在 External Libraries => python3.7(我用的这个版本) => site-packages =>  django/contrib/admin/templates/admin/).

    7. 在 area.html 文件中找到  {% block admin_change_form_document_ready %} (在66行) , 用下面代码覆盖全部 {% block admin_change_form_document_ready %} .

    7.1  area.html 中所有增加替换代码

                {% block admin_change_form_document_ready %}
                    <script type="text/javascript"
                            id="django-admin-form-add-constants"
                            src="{% static 'admin/js/change_form.js' %}"
                            {% if adminform and add %}
                            data-model-name="{{ opts.model_name }}"
                            {% endif %}>
                    </script>
                    <script type="text/javascript">
                        (function($) {
                            $('#id_city').change(function() {
                                let p_id = $('#id_province').val();
                                let c_id = $('#id_city').val();
                                $.get('/district/', {"p": p_id, "c": c_id }, function(a_info) {
                                    var area_info = $('#id_district').empty().append('<option value>' + '---------' + '</option>');
                                    $.each(a_info, function(i, area) {
                                        area_info.append('<option value="' + area + '">' + area + '</option>')
                                    });
                                    {% if change %}
                                        $("#id_district").find("option:contains({{ original.district }})").attr('selected', true);
                                    {% endif %}
                                });
                            });
    
                            $('#id_province').change(function() {
                                let p_id = $('#id_province').val();
                                $.get('/city/', { 'p': p_id }, function(c_info) {
                                    var city_info = $('#id_city').empty().append('<option value>' + '---------' + '</option>');
                                    $.each(c_info, function(i, city) {
                                        city_info.append('<option value="' + city + '">' + city + '</option>')
                                    });
                                    {% if change %}
                                        $("#id_city").find("option:contains({{ original.city }})").attr('selected', true);
                                        $("#id_city").trigger("change");
                                    {% endif %}
                                });
                            });
    
                            $.get('/province/', function(p_info) {
                                var province_info = $('#id_province').empty().append('<option value>' + '---------' + '</option>');
                                $.each(p_info, function(i, province) {
                                    province_info.append('<option value="' + province + '">' + province + '</option>')
                                });
                                {% if change %}
                                    $("#id_province").find("option:contains({{ original.province }})").attr('selected', true);
                                    $("#id_province").trigger("change");
                                {% endif %}
                            });
                        })(django.jQuery);
                    </script>
                {% endblock %}

    7.2  area.html 中所有代码

    {% extends "admin/base_site.html" %}
    {% load i18n admin_urls static admin_modify %}
    
    {% block extrahead %}{{ block.super }}
    <script type="text/javascript" src="{% url 'admin:jsi18n' %}"></script>
    {{ media }}
    {% endblock %}
    
    {% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}">{% endblock %}
    
    {% block coltype %}colM{% endblock %}
    
    {% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} change-form{% endblock %}
    
    {% if not is_popup %}
    {% block breadcrumbs %}
    <div class="breadcrumbs">
    <a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
    &rsaquo; <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
    &rsaquo; {% if has_view_permission %}<a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %}
    &rsaquo; {% if add %}{% blocktrans with name=opts.verbose_name %}Add {{ name }}{% endblocktrans %}{% else %}{{ original|truncatewords:"18" }}{% endif %}
    </div>
    {% endblock %}
    {% endif %}
    
    {% block content %}<div id="content-main">
    {% block object-tools %}
    {% if change %}{% if not is_popup %}
      <ul class="object-tools">
        {% block object-tools-items %}
          {% change_form_object_tools %}
        {% endblock %}
      </ul>
    {% endif %}{% endif %}
    {% endblock %}
    <form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="{{ form_url }}" method="post" id="{{ opts.model_name }}_form" novalidate>{% csrf_token %}{% block form_top %}{% endblock %}
    <div>
    {% if is_popup %}<input type="hidden" name="{{ is_popup_var }}" value="1">{% endif %}
    {% if to_field %}<input type="hidden" name="{{ to_field_var }}" value="{{ to_field }}">{% endif %}
    {% if save_on_top %}{% block submit_buttons_top %}{% submit_row %}{% endblock %}{% endif %}
    {% if errors %}
        <p class="errornote">
        {% if errors|length == 1 %}{% trans "Please correct the error below." %}{% else %}{% trans "Please correct the errors below." %}{% endif %}
        </p>
        {{ adminform.form.non_field_errors }}
    {% endif %}
    
    {% block field_sets %}
    {% for fieldset in adminform %}
      {% include "admin/includes/fieldset.html" %}
    {% endfor %}
    {% endblock %}
    
    {% block after_field_sets %}{% endblock %}
    
    {% block inline_field_sets %}
    {% for inline_admin_formset in inline_admin_formsets %}
        {% include inline_admin_formset.opts.template %}
    {% endfor %}
    {% endblock %}
    
    {% block after_related_objects %}{% endblock %}
    
    {% block submit_buttons_bottom %}{% submit_row %}{% endblock %}
    
    {% block admin_change_form_document_ready %}
        <script type="text/javascript"
                id="django-admin-form-add-constants"
                src="{% static 'admin/js/change_form.js' %}"
                {% if adminform and add %}
                    data-model-name="{{ opts.model_name }}"
                {% endif %}>
        </script>
    {% endblock %}
    
    {# JavaScript for prepopulated fields #}
    {% prepopulated_fields_js %}
    
    </div>
    </form></div>
    {% endblock %}

     8.效果

    9.访问admin出现问题:

    报错:UnicodeDecodeError: 'gbk' codec can't decode byte 0xa6 in position 9737: illegal multibyte sequence

    解决方法:https://www.cnblogs.com/djtang/p/10194811.html

     

    10.请各位大老多多指点! ===> 个人微信:DJtang009

  • 相关阅读:
    CodeForces 1105D-暴力BFS
    POJ 1258 Agri-Net (最小生成树)
    POJ 1251 Jungle Roads (最小生成树)
    hiho 1097 最小生成树一·Prim算法 (最小生成树)
    Codeforces 544E K Balanced Teams (DP)
    Codeforces 408D Long Path (DP)
    PTA L1题目合集(更新至2019.3)
    HDOJ 3308 LCIS (线段树)
    HDOJ 1698 Just a Hook (线段树)
    HDOJ 4267 A Simple Problem with Integers (线段树)
  • 原文地址:https://www.cnblogs.com/djtang/p/13547534.html
Copyright © 2011-2022 走看看