美文网首页
Django入门2

Django入门2

作者: 蜘蛛的梦呓 | 来源:发表于2018-04-12 00:10 被阅读0次

    今天本来想把这本书看完的,可是被几个小错误耽误了好多时间,其中一个错误重启服务竟然能运行成功了orz,真的烦躁。今天内容就383-397,明天继续加油。

    19.1 让用户能够输入数据

    19.1.1 添加新主题

    创建基于表达的页面的方法几乎与前面创建网页一样:定义一个 URL,编写一个视图函数并编写一个模板,一个主要区别是,需要导入包含表单的模块,forms.py

    1.在 Django 中,创建表单的最简单的方式是使用 ModelForm

    创建一个名为 forms.py 的文件,将其存储到 models.py 所在的目录中。

    from django import forms
    from .models import Topic, Entry
    
    
    class TopicForm(forms.ModelForm):
        class Meta:
            model = Topic
            fields = ['text']
            labels = {'text': ''}
    
    
    class EntryForm(forms.ModelForm):
        # Meta 存储用于管理模型的额外信息
        # Meta 类指出了表单基于的模型以及表单包含哪些字段
        class Meta:
            model = Entry
            fields = ['text']
            labels = {'text': ''}
            widgets = {'text': forms.Textarea(attrs={'cols': 80})}
    

    2.URL 模式

    from django.conf.urls import url
    from . import views
    
    '''定义 learning_logs 的 URL 模式'''
    # 该模块定义了可在管理网站中请求的所有 URL
    urlpatterns = [
    
        # url() 的第一个参数是正则表达式,第二个是要调用的视图函数,第三个是这个 URL 模式的名称
        # r:让 python 将接下来的字符串视为原始字符串
        # ^:查看字符串开头
        # $:查看字符串末尾
        # (r'^$'):即表示头尾没有任何东西的 URL(python 默认忽略项目的基础 URL(http://localhost:8080/)),
        # 所以这个正则表达式匹配基础 URL。
    
        # 主页
        url(r'^$', views.index, name='index'),
    
        # 显示所有主题
        url(r'^topics/$', views.topics, name='topics'),
    
        # 特定主题的详细页面
        url(r'^topics/(?P<topic_id>\d+)/$', views.topic, name='topic'),
        # learning_logs/urls.py
        # 用于添加新主题的网页
        url(r'^new_topic/$', views.new_topic, name='new_topic'),
    
        # 用于添加新条目的页面 http://localhost:8080/new_entry/id/ 的 URL 匹配
        # (?P<topic_id>\d+)捕获一个数字值,并将其存储到变量 topic_id 中
        # 请求的 URL 与这个模式匹配时, Django 将请求和主题 ID 发送给函数 new_entry()
        url(r'^new_entry/(?P<topic_id>\d+)/$', views.new_entry, name='new_entry'),
        # 用于编辑条目的页面
        url(r'^edit_entry/(?P<entry_id>\d+)/$', views.edit_entry, name='edit_entry'),
    
    ]
    app_name = "learning_logs"
    

    3.编写视图函数

    from django.shortcuts import render
    from django.http import HttpResponseRedirect, Http404
    # ModuleNotFoundError: No module named 'django.core.urlresolvers'
    # from django.core.urlresolvers import reverse
    from django.urls import reverse
    from django.contrib.auth.decorators import login_required
    
    from .models import Topic, Entry
    from .forms import TopicForm, EntryForm
    
    
    # Create your views here.
    
    
    def index(request):
        '''学习笔记的主页'''
        return render(request, 'learning_logs/index.html')
        # URL 请求与我们刚才定义的模式匹配时,Django 将在文件 views.py 中查找函数 index(),再将
        # 请求对象传递给这个视图函数。
    
    
    def topics(request):
        '''显示所有主题'''
        topics = Topic.objects.order_by('date_added')
        context = {'topics': topics}
        return render(request, 'learning_logs/topics.html', context)
    
    
    def topic(request, topic_id):
        '''显示单个主题以其所有条目'''
    
        topic = Topic.objects.get(id=topic_id)
        entries = topic.entry_set.order_by('-date_added')
        context = {'topics': topics, 'entries': entries}
        return render(request, 'learning_logs/topic.html', context)
    
    
    def new_topic(request):
        '''添加新主题'''
        # 确定 GET or POST,如果不为 Post,返回一个空表单。
        if request.method != 'POST':
            # 未提交数据:创建一个新表单
            form = TopicForm()
        else:
            # POST提交的数据,对数据进行处理,数据在 request.POST 中。
            form = TopicForm(request.POST)
            # 检查是否填写了所有必不可少的字段。(是否有效)
            if form.is_valid():
                form.save()
                return HttpResponseRedirect(reverse('learning_logs:topics'))
        context = {'form': form}
        return render(request, 'learning_logs/new_topic.html', context)
    
    
    def new_entry(request, topic_id):
        '''在特定的主题中添加新条目'''
        topic = Topic.objects.get(id=topic_id)
    
        if request.method != 'POST':
            # 未提交数据:创建一个新表单
            form = EntryForm()
        else:
            # POST提交的数据,对数据进行处理,数据在 request.POST 中。
            form = EntryForm(data=request.POST)
            if form.is_valid():
                new_entry = form.save(commit=False)
                new_entry.topic = topic
                new_entry.save()
                return HttpResponseRedirect(reverse('learning_logs:topic', args=[topic_id]))
    
        context = {'topic': topic, 'form': form}
        return render(request, 'learning_logs/new_entry.html', context)
    
    
    def edit_entry(request, entry_id):
        '''编辑既有条目'''
        entry = Entry.objects.get(id=entry_id)
        topic = entry.topic
        if topic.owner != request.user:
            raise Http404
    
        if request.method != 'POST':
            # 初次请求,使用当前条目填充表单
    
            form = EntryForm(instance=entry)
        else:
            # POST提交的数据,对数据进行处理
            form = EntryForm(instance=entry, data=request.POST)
            if form.is_valid():
                form.save()
                return HttpResponseRedirect(reverse('learning_logs:topic',
                                                    args=[topic.id]))
    
        context = {'entry': entry, 'topic': topic, 'form': form}
        return render(request, 'learning_logs/edit_entry.html', context)
    
    1. 编写模板(html 文件)

    base.html

    <p>
        <!--注册,注销页面-->
        <a href="{% url 'learning_logs:index' %}">Learning Log</a> -
        <a href="{% url 'learning_logs:topics' %}">Topics</a>
        {% if user.is_authenticated %}
        Hello, {{ user.username }}.
        <a href="{% url 'users:logout' %}">log out</a>
        {% else %}
        <a href="{% url 'users:login' %}">log in</a>
        {% endif %}
    </p>
    
    {% block content %}{% endblock %}
    

    edit_entry.html

    {% extends "learning_logs/base.html" %}
    
    {% block content %}
    
      <p><a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a></p>
        
      <p>Edit entry:</p>
        
      <form action="{% url 'learning_logs:edit_entry' entry.id %}" method='post'>
        {% csrf_token %}
        {{ form.as_p }}
        <button name="submit">save changes</button>
      </form>
    
    {% endblock content %}
    

    new_entry.html

    <!--new_entry.html-->
    {% extends "learning_logs/base.html" %}
    
    {% block content %}
    
      <p><a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a></p>
        
      <p>Add a new entry:</p>
      <form action="{% url 'learning_logs:new_entry' topic.id %}" method='post'>
        {% csrf_token %}
        {{ form.as_p }}
        <button name='submit'>add entry</button>
      </form>
        
    {% endblock content %}
    

    new_topic.html

    {% extends "learning_logs/base.html" %}
    
    {% block content %}
      <p>Add a new topic:</p>
    
      <form action="{% url 'learning_logs:new_topic' %}" method='post'>
        {% csrf_token %}
        {{ form.as_p }}
        <button name="submit">add topic</button>
      </form>
        
    {% endblock content %}
    

    topic.html

    {% extends 'learning_logs/base.html' %}
    
    {% block content %}
    
      <p>Topic: {{ topic }}</p>
    
      <p>Entries:</p>
      <ul>
      {% for entry in entries %}
        <li>
          <p>{{ entry.date_added|date:'M d, Y H:i' }}</p>
          <p>{{ entry.text|linebreaks }}</p>
        </li>
      {% empty %}
        <li>
          There are no entries for this topic yet.
        </li>
      {% endfor %}
      </ul>
    
    {% endblock content %}
    

    topics.html

    {% extends "learning_logs/base.html" %}
    
    {% block content %}
    
      <p>Topics</p>
    
      <ul>
        {% for topic in topics %}
          <li>
            <a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a>
         </li>
        {% empty %}
          <li>No topics have been added yet.</li>
        {% endfor %}
      </ul>
    
    {% endblock content %}
    

    书上基本都是按这几步走,大概对照一下就好了,我不想按着书上那样一步步写下去(其实是懒),需要注意的是:

    1.ModuleNotFoundError: No module named 'django.core.urlresolvers'(按书上写会报这个错误,Django版本不同所致),解决方法:这样导入 from django.urls import reverse 即可;

    2.还有 learning_logs 的 URL 模式 urls.py 按书上写会报 NameError: name 'include' is not defined 这个错误,添加一个 app_name = "learning_logs(应用的名称)"即可解决。

    19.2 创建用户账户

    19.2.1 创建应用程序 users

    首先创建一个名为 users 的应用程序。

    python manage.py startapp users
    

    1.将应用程序 users 添加到 settings.py

    #--snip--
    INSTALLED_APPS = (
        #--snip--
        'learning_logs',
        'users',
    )
    #--snip--
    

    这样 Django 将把应用程序 users 包含到项目中。

    2.包含应用程序 users 的 URL

    根目录的 urls.py

    from django.conf.urls import include, url
    from django.contrib import admin
    
    # 该模块定义了可在管理网站中请求的所有 URL
    
    urlpatterns = [
        # 去掉第一个url后的include(),不然报错
        url(r'^admin/', admin.site.urls),
        url(r'^users/', include('users.urls', namespace='users')),
        # 实参 namespace,让我们能够将 learning_logs 的 URL 同项目中的其他 URL 区分开来。
        url(r'', include('learning_logs.urls', namespace='learning_logs')),
    ]
    

    3.users 的 URL 模式

    在目录 learning_log/users 中,新建 urls.py 。

    # learning_log/users/urls.py
    '''为应用程序 users 定义 URL 模式'''
    from django.conf.urls import url
    from django.contrib.auth.views import login
    
    from . import views
    
    urlpatterns = [
        # 登录页面
        # 添加的代码与任何以 users 开头的URL(如http://localhost:8000/users/login/)都匹配。
        # 默认视图实参为 login(不是views.login)告诉 Django 将请求发送给视默认视图 login。接着传递了一个字典指定要查找的模板。
        url(r'^login/$', login, {'template_name': 'users/login.html'}, name='login'),
    
        # 注销
        url(r'^logout/$', views.logout_view, name='logout'),
    
        # 注册
        # url(r'^register/$', views.register, name='register'),
    
    ]
    app_name = "users"
    

    2.编写视图函数

    #learning_log\users\views.py
    
    from django.shortcuts import render
    from django.http import HttpResponseRedirect
    from django.urls import reverse
    from django.contrib.auth import logout
    
    
    def logout_view(request):
        """注销"""
        logout(request)
        return HttpResponseRedirect(reverse('learning_logs:index'))
    

    3.编写模板(html)

    按这样新建文件夹 learning_log\users\templates\users

    login.html

    <!--login.html-->
    {% extends "learning_logs/base.html" %}
    
    {% block content %}
    
    <!--如果表单的 errors 属性被设置,我们将显示一条错误信息-->
    {% if form.errors %}
    <p>Your username and password didn't match. Please try again.</p>
    {% endif %}
    
    <!--链接到登录页面-->
    <form method="post" action="{% url 'users:login' %}">
        {% csrf_token %}
        {{ form.as_p }}
    
        <button name="submit">log in</button>
        <!--隐藏表单元素—— next,其中的实参 value 告诉 Django 在用户成功登陆后将其重定向到主页-->
        <input type="hidden" name="next" value="{% url 'learning_logs:index' %}"/>
    </form>
    
    {% endblock content %}
    

    因为登录页面是使用 Django 的默认视图login,所以可以不用写视图函数,只需要告诉 Django 去哪里查找我们编写的模板。

    今天就这样了,我觉得这样写下来能更好的把握 Django 的整体架构,不会那么容易被书不断重复的内容弄晕,具体细节请看书上的详细内容,就不一步步写了(会把新人弄晕的),好了今天就到这里了(看得好少),谢谢大家了。

    相关文章

      网友评论

          本文标题:Django入门2

          本文链接:https://www.haomeiwen.com/subject/restkftx.html