django快速笔记

1. Django常用命令

  1. 创建django项目
    django-admin startproject mysite
    mysite/							#项目的容器,可以任意改名
    manage.py						#管理该项目的工具
    mysite/							#一个python包i,容纳该项目
        __init__.py					#空文件,python的规则中,代表这是一个包
        settings.py					#该项目的配置文件
        urls.py						#项目的URL请求映射规则
        asgi.py						#项目和ASGI兼容的WEB服务器的入口
        wsgi.py						#项目和WSGI兼容的WEB服务器的入口
    
  2. 开启项目
    python manage.py runserver
    python manage.py runserver 8080
    python manage.py runserver 0.0.0.0:8000
  3. 创建一个应用(一个项目包含多个应用)
    python manage.py startapp polls
  4. 数据库迁移:
    python manage.py migrate
  5. 根据APP中定义的模型生产迁移事项清单(迁移:根据APP的模型定义models.py,在数据库中创建对应的数据表和字段)
    python manage.py makemigrations polls
  6. 查看迁移所要执行的SQL语句
    python manage.py sqlmigrate polls 0001
  7. 自动检查项目中的问题
    python manage.py check
  8. 打开操作当前项目的命令行(可操作数据库API)
    python manage.py shell
  9. 创建能够登录后台管理页面的管理员账户
    python manage.py createsuperuser

2. URL映射


polls/urls.py

from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='index'),
]


mysite/urls.py

from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('polls/', include('polls.urls')),
    path('admin/', admin.site.urls),
]

每当django遇到include时,会截断匹配到的url部分,然后将剩余的url部分发送到include的参数所指向的URLConf以供进一步处理


path(route, view, kwargs=None, name=None)

参数用法
route字符串,类似于正则表达式,URL匹配规则
view视图函数或者是一个Include
kwargs向视图函数或方法传递附加参数
name该条url的名字,用于在django任意地方引用这个url,主要用于模板

3. 安装项目


mysite/settings.py

INSTALLED_APPS = [
    'polls.apps.PollsConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

4. 数据库


mysite/settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}
字段内容
ENGINE可选的值有:
‘django.db.backends.sqlite3’,
‘django.db.backends.postgresql’,
‘django.db.backends.mysql’,
‘django.db.backends.oracle’
NAME数据库名称,SQLite数据库时,是一个数据库文件的绝对路径

数据库迁移:python manage.py migrate
该命令会查看settings.py中的INSTALLED_APPS配置,并根据数据库配置来迁移这些APP的数据库文件至新的数据库中

5. 模型


polls/models.py

from django.db import models


class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')


class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

  1. 每个模型都是django.db.models.Model类的子类
  2. 每个模型的类变量都是模型的一个数据库字段
  3. 每个类变量都是Field类的实例。如,字符字段表示为CharField,日期时间字段表示为DateTimeField
  4. 每个类变量的名字就是数据库中代表该模型表的一个列名。
  5. django支持常用数据库关系,多对一,一对多,一对一。如,ForeignKey代表一个关联关系

编辑模型三步骤:

  • 编辑Models.py文件
  • 运行 python manage.py makemigrations 为模型的改变生成迁移文件
  • 运行 python manage.py migrate 来应用数据库迁移

6. 数据库操作

打开当前项目的交互命令行:python manage.py shell


>>> from polls.models import Choice, Question  # Import the model classes we just wrote.

# No questions are in the system yet.
>>> Question.objects.all()
<QuerySet []>

# Create a new Question.
# Support for time zones is enabled in the default settings file, so
# Django expects a datetime with tzinfo for pub_date. Use timezone.now()
# instead of datetime.datetime.now() and it will do the right thing.
>>> from django.utils import timezone
>>> q = Question(question_text="What's new?", pub_date=timezone.now())

# Save the object into the database. You have to call save() explicitly.
>>> q.save()

# Now it has an ID.
>>> q.id
1

# Access model field values via Python attributes.
>>> q.question_text
"What's new?"
>>> q.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=datetime.timezone.utc)

# Change values by changing the attributes, then calling save().
>>> q.question_text = "What's up?"
>>> q.save()

# objects.all() displays all the questions in the database.
>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>]>

为了调用Question.objects.all()时便于展示已经创建出来的对象,添加__str__()方法

polls/models.py

from django.db import models

class Question(models.Model):
    # ...
    def __str__(self):
        return self.question_text

class Choice(models.Model):
    # ...
    def __str__(self):
        return self.choice_text

给模型添加自定以的方法,添加
polls/models.py

import datetime

from django.db import models
from django.utils import timezone


class Question(models.Model):
    # ...
    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

>>> from polls.models import Choice, Question

# Make sure our __str__() addition worked.
>>> Question.objects.all()
<QuerySet [<Question: What's up?>]>

# Django provides a rich database lookup API that's entirely driven by
# keyword arguments.
>>> Question.objects.filter(id=1)
<QuerySet [<Question: What's up?>]>
>>> Question.objects.filter(question_text__startswith='What')
<QuerySet [<Question: What's up?>]>

# Get the question that was published this year.
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.get(pub_date__year=current_year)
<Question: What's up?>

# Request an ID that doesn't exist, this will raise an exception.
>>> Question.objects.get(id=2)
Traceback (most recent call last):
    ...
DoesNotExist: Question matching query does not exist.

# Lookup by a primary key is the most common case, so Django provides a
# shortcut for primary-key exact lookups.
# The following is identical to Question.objects.get(id=1).
>>> Question.objects.get(pk=1)
<Question: What's up?>

# Make sure our custom method worked.
>>> q = Question.objects.get(pk=1)
>>> q.was_published_recently()
True

# Give the Question a couple of Choices. The create call constructs a new
# Choice object, does the INSERT statement, adds the choice to the set
# of available choices and returns the new Choice object. Django creates
# a set to hold the "other side" of a ForeignKey relation
# (e.g. a question's choice) which can be accessed via the API.
>>> q = Question.objects.get(pk=1)

# Display any choices from the related object set -- none so far.
>>> q.choice_set.all()
<QuerySet []>

# Create three choices.
>>> q.choice_set.create(choice_text='Not much', votes=0)
<Choice: Not much>
>>> q.choice_set.create(choice_text='The sky', votes=0)
<Choice: The sky>
>>> c = q.choice_set.create(choice_text='Just hacking again', votes=0)

# Choice objects have API access to their related Question objects.
>>> c.question
<Question: What's up?>

# And vice versa: Question objects get access to Choice objects.
>>> q.choice_set.all()
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
>>> q.choice_set.count()
3

# The API automatically follows relationships as far as you need.
# Use double underscores to separate relationships.
# This works as many levels deep as you want; there's no limit.
# Find all Choices for any question whose pub_date is in this year
# (reusing the 'current_year' variable we created above).
>>> Choice.objects.filter(question__pub_date__year=current_year)
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>

# Let's delete one of the choices. Use delete() for that.
>>> c = q.choice_set.filter(choice_text__startswith='Just hacking')
>>> c.delete()

7. 后台管理

创建后台管理员:python manage.py createsuperuser
默认管理员地址:http://127.0.0.1:8000/admin/


管理页面添加应用
<polls/admin.py>

from django.contrib import admin

from .models import Question, Choice

admin.site.register(Question)
admin.site.register(Choice)

8. 视图

添加其他视图
<polls/views.py>

from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from .models import Choice, Question

def detail(request, question_id):
    return HttpResponse("You're looking at question %s." % question_id)

def results(request, question_id):
    response = "You're looking at the results of question %s."
    return HttpResponse(response % question_id)

def vote(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
        selected_choice = question.choice_set.get(pk=request.POST["choice"])
    except (KeyError, Choice.DoesNotExist):
        # Redisplay the question voting form.
        return render(
            request,
            "polls/detail.html",
            {
                "question": question,
                "error_message": "You didn't select a choice.",
            },
        )
    else:
        selected_choice.votes += 1
        selected_choice.save()
        # Always return an HttpResponseRedirect after successfully dealing
        # with POST data. This prevents data from being posted twice if a
        # user hits the Back button.
        return HttpResponseRedirect(reverse("polls:results", args=(question.id,)))

HttpResponseRedirect对象只需要一个参数,即重定向后的路径。处理表单post数据时,应当总是返回一个 HttpResponseRedirect对象
可以通过reverse函数来动态生成路径,避免硬编码


将这些视图添加到应用的URL映射模块中

<polls/urls.py>

from django.urls import path

from . import views

urlpatterns = [
    # ex: /polls/
    path('', views.index, name='index'),
    # ex: /polls/5/
    path('<int:question_id>/', views.detail, name='detail'),
    # ex: /polls/5/results/
    path('<int:question_id>/results/', views.results, name='results'),
    # ex: /polls/5/vote/
    path('<int:question_id>/vote/', views.vote, name='vote'),
]

URL映射模块中的<int:question_id>中的int代表类型,quesiton_id是该参数的命名
该question_id命名所代表的参数将会被传递给视图函数对应的同名参数


每个视图必须要做的只有两件事:

  1. 返回一个包含请求页面内容的HttpResponse对象
  2. 或者抛出一个异常,比如Http404

视图函数从数据库中取出数据,并展示

<polls/views.py>

from django.http import HttpResponse

from .models import Question


def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    output = ', '.join([q.question_text for q in latest_question_list])
    return HttpResponse(output)

# Leave the rest of the views (detail, results, vote) unchanged

8. 模板

配置模板:在应用下创建下创建名为templates的文件夹,再创建应用同名的文件夹,模板放在该目录下
即:polls/templates/polls/index.html

  1. 项目的 TEMPLATES 配置项描述了 Django 如何载入和渲染模板。
  2. 默认的设置文件设置了 DjangoTemplates 后端,并将 APP_DIRS 设置成了 True。这一选项将会让 DjangoTemplates 在每个 INSTALLED_APPS 文件夹中寻找 “templates” 子目录。

使用模板,通过给模板传入一个context字典:

<polls/views.py>

from django.http import HttpResponse
from django.template import loader

from .models import Question


def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    template = loader.get_template('polls/index.html')
    context = {
        'latest_question_list': latest_question_list,
    }
    return HttpResponse(template.render(context, request))

快捷函数:render(),会返回一个HttpResponse对象

from django.shortcuts import render

from .models import Question


def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    context = {'latest_question_list': latest_question_list}
    return render(request, 'polls/index.html', context)

<polls/templates/polls/index.html>

{% if latest_question_list %}
    <ul>
    {% for question in latest_question_list %}
        <li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
    {% endfor %}
    </ul>
{% else %}
    <p>No polls are available.</p>
{% endif %}

django模板文档:https://docs.djangoproject.com/zh-hans/4.1/topics/templates/

{{ question.question_text }}
模板系统会首先对question使用字典查找,即question.get(‘question_text’)
如果字典查找失败,会尝试属性查找,即question.question
如果属性查找失败,会尝试列表查找,即question[数字]操作

{% for choice in question.choice_set.all %}
question.choice_set.all会被解释为python代码question.choice_set.all(),返回一个可迭代的Choice对象,这一对象可在{% for %}标签内部使用

{% url %}
去除模板中的硬编码URL

<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>

改写为:

<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>
#或者为了区分不同的App具有同样名叫detail的url命名,可采用命名空间
<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
#采用命名空间时,需要在urls.py中添加
app_name = "polls"

<polls/templates/polls/results.html>

<h1>{{ question.question_text }}</h1>

<ul>
{% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>

<a href="{% url 'polls:detail' question.id %}">Vote again?</a>


<polls/templates/polls/detail.html>

<h1>{{ question.question_text }}</h1>

<hr />
<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
<fieldset>
    <legend><h1>{{ question.question_text }}</h1></legend>
    {% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
    {% for choice in question.choice_set.all %}
        <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}">
        <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
    {% endfor %}
</fieldset>
<input type="submit" value="Vote">
</form>

9. 抛出404错误

<polls/views.py>

from django.http import Http404
from django.shortcuts import render

from .models import Question
# ...
def detail(request, question_id):
    try:
        question = Question.objects.get(pk=question_id)
    except Question.DoesNotExist:
        raise Http404("Question does not exist")
    return render(request, 'polls/detail.html', {'question': question})

快捷函数:get_object_or_404(),先尝试用get获取一个对象,如果不存在就抛出Http404错误

from django.shortcuts import get_object_or_404, render

from .models import Question
# ...
def detail(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/detail.html', {'question': question})

<polls/templates/polls/detail.html>

<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>

10. 表单

<polls/templates/polls/detail.html>

<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
<fieldset>
    <legend><h1>{{ question.question_text }}</h1></legend>
    {% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
    {% for choice in question.choice_set.all %}
        <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}">
        <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
    {% endfor %}
</fieldset>
<input type="submit" value="Vote">
</form>

11. 静态文件

  1. 创建polls/static/polls目录
  2. polls/static/polls目录下创建style.css
  3. style.css中填写内容
    li a {
        color: green;
    }
    
  4. 模板polls/templates/polls/index.html头文件中添加引用该css
    {% load static %}
    <link rel="stylesheet" href="{% static 'polls/style.css' %}">
    
  5. 重启django服务器

12. 自定义后台管理界面

  1. 表单排序
    from django.contrib import admin
    
    from .models import Question
    
    
    class QuestionAdmin(admin.ModelAdmin):
        fields = ["pub_date", "question_text"]
    
    
    admin.site.register(Question, QuestionAdmin)
    
  2. 表单拆分字段
    from django.contrib import admin
    
    from .models import Question
    
    
    class QuestionAdmin(admin.ModelAdmin):
        fieldsets = [
            (None, {"fields": ["question_text"]}),
            ("Date information", {"fields": ["pub_date"]}),
        ]
    
    
    admin.site.register(Question, QuestionAdmin). 
    
  3. 创建Question时,自动创建Choice
    from django.contrib import admin
    
    from .models import Choice, Question
    
    
    class ChoiceInline(admin.StackedInline):
        model = Choice
        extra = 3
    
    
    class QuestionAdmin(admin.ModelAdmin):
        fieldsets = [
            (None, {"fields": ["question_text"]}),
            ("Date information", {"fields": ["pub_date"], "classes": ["collapse"]}),
        ]
        inlines = [ChoiceInline]
    
    
    admin.site.register(Question, QuestionAdmin)
    
  4. 创建Querstion时,自动创建Choice,横向展示
    class ChoiceInline(admin.TabularInline):
        ...
    
  5. 展示Question列表时,额外展示其他字段
    class QuestionAdmin(admin.ModelAdmin):
        # ...
        list_display = ["question_text", "pub_date", "was_published_recently"]	
    
  6. 使用装饰器改进展示效果
    #<polls/models.py>
    
    from django.contrib import admin
    
    
    class Question(models.Model):
        # ...
        @admin.display(
            boolean=True,
            ordering="pub_date",
            description="Published recently?",
        )
        def was_published_recently(self):
            now = timezone.now()
            return now - datetime.timedelta(days=1) <= self.pub_date <= now
    
  7. 添加一个过滤器便于查找
    class QuestionAdmin(admin.ModelAdmin):
    	# ...
    	list_filter = ["pub_date"]
    
  8. 添加搜索功能
    class QuestionAdmin(admin.ModelAdmin):
    	# ...
    	search_fields = ["question_text"]
    
  9. 自定义后台界面和风格
    • 修改settings.py
      #<mysite/settings.py>,添加DIRS选项
      
      TEMPLATES = [
          {
              "BACKEND": "django.template.backends.django.DjangoTemplates",
              "DIRS": [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",
                  ],
              },
          },
      ]
      
    • 创建mysite/templates/admin目录
    • 从django安装目录中复制django/contrib/admin/templates/admin/base_site.htmlmysite/templates/admin目录中
    • 修改base_site.html内容
      {% block branding %}
      <h1 id="site-name"><a href="{% url 'admin:index' %}">Polls Administration</a></h1>
      {% endblock %}	
      
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值