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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM