亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

表單Form對象的使用及如何構建復雜的QuerySet

發布時間:2021-10-29 09:12:32 來源:億速云 閱讀:160 作者:柒染 欄目:大數據

本篇文章為大家展示了表單Form對象的使用及如何構建復雜的QuerySet,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

一、利用Django創建表單

Django包含兩個基類可構建表單,如下所示:

  1. Form 可構建標準的表單

  2. ModelForm 可構建與模型實例相關聯的表單

1. 標準表單Form

首先 在應用程序目錄中創建 forms.py 文件,代碼如下:

from django import forms

class EmailPostForm(forms.Form):
    name = forms.CharField(max_length=25)
    email = forms.EmailField()
    to = forms.EmailField()
    comments = forms.CharField(required=False, widget=forms.Textarea)
  • CharField 該字段類型顯示為 <input type="text">

  • widget 為字段所使用的插件,在 comments 字段中使用了 Textarea 插件

  • EmailField 需要使用有效的電子郵件地址;否則,字段驗證將拋出 forms.ValidationError 異常

  • required 表示該字段是否必填項

有效的表單字段列表請參照:點擊此處

接下來views.py 中使用 Form 表單對象

from .forms import EmailPostForm

def post_share(request, post_id):
    post = get_object_or_404(Post, id=post_id, status='published')
    if request.method == 'POST':
        form = EmailPostForm(request.POST)
        if form.is_valid():
            cd = form.cleaned_data
            # ...
    else:
        form = EmailPostForm()
    return render(request, 'blog/post/share.html', {'post': post, 'form': form})

上述視圖工作方式如下:

  • 定義了 post_share 視圖,并接收 request 對象和 post_id 變量作為參數

  • 采用 get_object_or_404 快捷方式,并通過 ID 檢索帖子,以確保檢索的狀態為 published

  • 根據 request.method == 'POST' 方法區分 POST 請求還是 GET 請求

表單處理流程如下:

  1. 當視圖為 GET 請求時,創建一個新的 form 實例,并用于顯示模板中的空表單: form = EmailPostForm()

  2. 當為 POST 請求時,通過包含于 request.POST 中的提交數據生成一個表單實例:form = EmailPostForm(request.POST)

  3. 利用表單 is_valid() 方法驗證所提交的數據。如果作一字段包含了無效數據,將返回 False。通過訪問 form.errors 可查看驗證錯誤列表

  4. 若表單正確,通過訪問 form.cleaned_data 將對驗證后的數據進行檢索。該屬性表示為表單字段及其對應值的字典。

最后 在HTML模板中使用 Form 對象:

{% extends "blog/base.html" %}

{% block title %}Share a post{% endblock %}

{% block content %}
    {% if sent %}
        <h2>E-mail successfully sent</h2>
        <p>
            "{{ post.title }}" was successfully sent to {{ form.cleaned_data.to }}.
        </p>
    {% else %}
        <h2>Share "{{ post.title }}" by e-mail</h2>
        <form action="." method="post">
            {{ form.as_p }}
            {% csrf_token %}
            <input type="submit" value="Send e-mail">
        </form>
    {% endif %}
{% endblock %}

此處通知Django利用 as_p 方法將字段顯示為 <p> 中的字段。除此之外,還可利用 as_ul 作為無序列表顯示表單;或者利用 as_table 作為表予以顯示。如果需要顯示每個字段,可遍歷相關字段,如下所示:

{% for field in form%}
<div>
 {{ field.errors }}
 {{ field.label_tag }} {{ field }}
</div>
{% endfor %}

2. 模型表單ModelForm

首先 創建用于評論帖子的模型:

class Comment(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
    name = models.CharField(max_length=80)
    email = models.EmailField()
    body = models.TextField()
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    active = models.BooleanField(default=True)

    class Meta:
        ordering = ('created',)

    def __str__(self):
        return 'Comment by {} on {}'.format(self.name, self.post)
  • ForeignKey 以外鍵關聯帖子

  • related_name 可對對應關系表進行跨表查詢。定義完畢后,可通過 comment.post 檢索評論對象的帖子,也可采用 post.comments.all() 檢索某個帖子的全部評論;如果沒有定義該值,Django將使用 模型名稱_set (如 comment_set )這一形式命名相關的對象管理器

關于多對一關系,可點擊此處了解更多內容

接著 創建模型中的表單,編輯 應用程序 目錄下的 forms.py 文件,添加如下代碼:

from .models import Comment

class CommentForm(forms.ModelForm):
    class Meta:
        model = Comment
        fields = ('name', 'email', 'body')
  • model 指定使用哪一個模型創建表單

  • fields 顯式地通知當前框架希望在表單中包含哪些字段;或者采用 exclude 定義希望排除的字段。

然后 在視圖View中使用ModelForms,修改 views.py 文件的 post_detail() 方法如下:

from .models import Post, Comment
from .forms import EmailPostForm, CommentForm

def post_detail(request, year, month, day, post):
    post = get_object_or_404(Post, slug=post, status='published', publish__year=year, publish__month=month,
                             publish__day=day)

    # 通過post對象查找關聯的comment對象
    comments = post.comments.filter(active=True)
    new_comment = None

    if request.method == 'POST':
        comment_form = CommentForm(data=request.POST)
        if comment_form.is_valid():
            new_comment = comment_form.save(commit=False)
            new_comment.post = post
            new_comment.save()
    else:
        comment_form = CommentForm()

    return render(request, 'blog/post/detail.html',
                  {'post': post, 'comments': comments, 'new_comment': new_comment, 'comment_form': comment_form})
  • comments = post.comments.filter(active=True) 使用了 post_detail 視圖顯示帖子及其評論內容,并針對該帖子加入了QuerySet以過濾檢索評論

  • new_comment = comment_form.save(commit=False) 創建表單所鏈接的模型實例。如果采用 commit=False 則會創建模型實例,但不會將其保存至數據庫中

  • new_comment.post = post 修改ModelForms的屬性值

  • new_comment.save() 保存至數據庫中

最后 在HTML模板中顯示:

    <!-- 顯示評論數量 -->
    {% with comments.count as total_comments %}
        <h3>
            {{ total_comments }} comment{{ total_comments|pluralize }}
        </h3>
    {% endwith %}

    <!-- 顯示所有評論內容 -->
    {% for comment in comments %}
        <div class="comment">
            <p class="info">
                Comment {{ forloop.counter }} by {{ comment.name }}
                {{ comment.created }}
            </p>
            {{ comment.body|linebreaks }}
        </div>
    {% empty %}
        <p>There are no comments yet.</p>
    {% endfor %}

    <!-- 顯示添加評論的表單 -->
    {% if new_comment %}
        <h3>Your comment has been added.</h3>
    {% else %}
        <h3>Add a new comment</h3>
        <form action="." method="post">
            {{ comment_form.as_p }}
            {% csrf_token %}
            <p><input type="submit" value="Add comment"></p>
        </form>
    {% endif %}
  • {% with %} 標簽可將某個值賦予可用的新變量中,直到遇到 {% endwith %} 標簽。

  • pluralize 過濾器將返回包含字母 s 的復數字符串形式。

二、使用 django-taggit 添加標簽功能

Django-taggit 源碼地址

1. 安裝django-taggit

pip/pipenv install django_taggit

2. 在 settings.py 文件中注冊 taggia

INSTALLED_APPS = [
    ...
    'taggit',
]

3. 將 djnago-taggit 提供的 TaggableManager 管理器添加到需要使用 tag 的模型中

from taggit.managers import TaggableManager

class Post(models.Model):
    ...
    tags = TaggableManager()

4. 生成數據庫遷移

python manage.py makemigrations blog(應用名稱)
python manage.py migrate

遷移完成后,運行服務器,可以 Django管理 頁面中管理所有 標簽(tags)

5. 在shell中考察如何使用tags管理器

>>> from blog.models import Post
>>> post = Post.objects.get(id=1)
>>> post.tags.add('music', 'jazz', 'django')
>>> post.tags.all()
<QuerySet [<Tag: music>, <Tag: django>, <Tag: jazz>]>

>>> post.tags.remove('django')
>>> post.tags.all()
<QuerySet [<Tag: music>, <Tag: jazz>]>

6. 在HTML模板中顯示 Tags

<p class="tags">Tags: {{ post.tags.all|join:", " }}</p>
  • join 模板過濾器類似于字符串的 join() 方法,并添加包含指定字符串到相關元素中。

7. 在視圖Views中使用 Tags

修改 應用程序 目錄的 views.py 文件,代碼如下:

from taggit.models import Tag

def post_list(request, tag_slug=None):
    object_list = Post.published.all()

    tag = None
    if tag_slug:
        tag = get_object_or_404(Tag, slug=tag_slug)
        object_list = object_list.filter(tags__in=[tag])

    paginator = Paginator(object_list, 3)  # 每頁3條記錄
    page = request.GET.get('page')
    try:
        posts = paginator.page(page)
    except PageNotAnInteger:
        # 如為無效頁碼則跳轉到第1頁
        posts = paginator.page(1)
    except EmptyPage:
        # 如果頁數超出范圍則跳轉到最后一頁
        posts = paginator.page(paginator.num_pages)
    return render(request, 'blog/post/list.html', {'posts': posts, 'page': page, 'tag': tag})
  • post_list 接收可選的 tag_slug 參數,默認值為 None 并包含于URL中

  • 在構建初始的QuerySet、檢索發布的全部帖子,如果存在標簽slug,將通過 get_object_or_404() 獲得 Tag 對象

  • 隨后,通過slug過濾帖子列表。

  • 最后調整視圖下方的 render() 函數,將 tag 變量會至HTML模板中。

添加額外的URL路徑,通過標簽列出帖子:

path('tag/<slug:tag_slug>/', views.post_list, name='post_list_by_tag'),

前端面HTML模板代碼修改如下:

{% extends "blog/base.html" %}

{% block title %}My Blog{% endblock %}

{% block content %}
    <h2>My Blog</h2>
    {% if tag %}
        <h3>Posts tagged with "{{ tag.name }}"</h3>
    {% endif %}
    {% for post in posts %}
        <h3>
            <a href="{{ post.get_absolute_url }}">
                {{ post.title }}
            </a>
        </h3>
        <p class="tags">
            Tags:
            {% for tag in post.tags.all %}
                <a href="{% url "blog:post_list_by_tag" tag.slug %}">
                    {{ tag.name }}
                </a>
                {% if not forloop.last %}, {% endif %}
            {% endfor %}

        </p>
        <p class="date">
            Published {{ post.publish }} by {{ post.author }}
        </p>
        {{ post.body|truncatewords:30|linebreaks }}
        {% include 'pagination.html' with page=posts %}
    {% endfor %}
{% endblock %}
  • {% url "blog:post_list_by_tag" tag.slug %} 使URL名稱以及slug標簽作為其參數

三、構建復雜的QuerySet

我們將在 post_detail 視圖中構建復雜的QuerySet,修改 應用程序 目錄下的 views.py 文件,添加如下代碼:

from django.db.models import Count
  • Count 為Django ORM中的Count聚合函數,其它聚合函數可訪問如下地址

render() 之前,在 post_detail 視圖中添加下列代碼:

    post_tag_ids = post.tags.values_list('id', flat=True)
    similar_posts = Post.published.filter(tags__in=post_tag_ids).exclude(id=post.id)
    similar_posts = similar_posts.annotate(same_tags=Count('tags')).order_by('-same_tags', '-publish')[:4]

    return render(request, 'blog/post/detail.html',
                  {'post': post, 'comments': comments, 'new_comment': new_comment, 'comment_form': comment_form,
                   'similar_posts': similar_posts})

上述代碼執行下列操作:

  1. 針對當前帖子的標簽,標簽Python ID列表。values_list() 返回包含指定字段的元組。將 flat=True 傳入,可獲得形如 [1,2,3,...] 的列表。

  2. 獲取包含此類標簽的全部帖子,并排除當前帖子本身。

  3. 使用 Count 函數生成一個計算后的字段,即 same_tags。該字段包含了與所有查詢標簽所共有的標簽號

  4. 通過標簽號和發布日期對結果進行排序。此處僅檢索前4個帖子。

  5. similar_posts 放入上下文字典中。

最后,在HTML模板中顯示:

    <h3>Similar posts</h3>
    {% for post in similar_posts %}
        <p>
            <a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
        </p>
    {% empty %}
        There are no similar posts yet.
    {% endfor %}

至此,可向用戶推薦標簽相似的帖子的功能。

上述內容就是表單Form對象的使用及如何構建復雜的QuerySet,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

平定县| 隆尧县| 集贤县| 昭苏县| 伊春市| 高清| 大足县| 五华县| 邵阳县| 黔西县| 红河县| 河南省| 体育| 化州市| 阿克陶县| 廉江市| 银川市| 滨海县| 闽清县| 仙居县| 茂名市| 湖北省| 长宁县| 阳江市| 新建县| 高清| 大邑县| 博兴县| 杨浦区| 鹤岗市| 奎屯市| 游戏| 高要市| 红桥区| 双流县| 雷州市| 灵武市| 鹰潭市| 永仁县| 娱乐| 柳州市|