検索

Python-ジャンゴ

Feb 15, 2017 pm 03:30 PM
djangopython

準備

新しい Django プロジェクトを作成します

# 新建一个django项目
$ django-admin startproject mysite
# 新建一个app
$ django-admin startapp blog

プロジェクトの構造

├── blog
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── manage.py
└── mysite
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py
# mysite/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog', 
    'markdown2'
]
$ python3 manage.py runserver

$ python manage.py collectstatic

通常、URL は urls.py で構成され、モデルは models.py で構成され、ビューは views.py で構成されます。

urls.py

関数ビューFunction views

1. Add an import:  from my_app import views
2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')

Class-based views

1. Add an import:  from other_app.views import Home
2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')

Including another URLconf

1. Import the include() function: from django.conf.urls import url, include
2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
# blog/urls.py

from django.conf.urls import url
from blog import views

urlpatterns = [
    url(r'^blog/$', views.IndexView.as_view(), name='index'),
    url(r'^blog/article/(?P<article_id>\d+)$', views.ArticleDetailView.as_view(), name='detail'),
    url(r'^blog/category/(?P<cate_id>\d+)$', views.CategoryView.as_view(), name='category'),
    url(r'^blog/tag/(?P<tag_id>\d+)$', views.TagView.as_view(), name='tag'),
]</tag_id></cate_id></article_id>

使用(?Pd+)的形式捕获值给中得参数,比如(?Pd+),当访问/blog/article/3时,将会将3捕获给article_id,这个值会传到views.ArticleDetailView。

# mysite/urls.py

from django.conf.urls import url, include
from django.contrib import admin
from blog import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'', include('blog.urls', namespace='blog', app_name='blog'))
]

其中namespace参数为我们指定了命名空间,这说明这个urls.py中的url是blog app下的,这样即使不同的app下有相同url也不会冲突了。

假设用户要访问某篇文章,它会自动解析 blog:detail 这个视图函数对应的 url,并且把 article.pk(文章的主键)传递给detail视图函数,details就是我们在blog/urls.py中指定的name

<a>{{ article.title }}</a>

如果要访问某个目录

<a>{{ category.name }}</a>

models.py

django.db.models是orm框架的基础,在blog/models.py中新建Article, Category, Tag三个model。

class Article(models.Model):
    STATUS_CHOICES = (
        ('d', 'Draft'),
        ('p', 'Published'),
    )
    
    # 仍然使用默认的 objects 作为 manager 的名字
    objects = ArticleManager()

    title = models.CharField('标题', max_length=70)
    body = models.TextField('正文')
    created_time = models.DateTimeField('创建时间', auto_now_add=True)
    last_modified_time = models.DateTimeField('修改时间', auto_now=True)
    status = models.CharField('文章状态', max_length=1, choices=STATUS_CHOICES)
    # blank和null要同时设置为null,详情参考官方文档
    abstract = models.CharField('摘要', max_length=54, blank=True, null=True, 
                                help_text="可选,如若为空将摘取正文的前54个字符")
    views = models.PositiveIntegerField('浏览量', default=0)
    likes = models.PositiveIntegerField('点赞数', default=0)
    topped = models.BooleanField('置顶', default=False)
    
    category = models.ForeignKey('Category', verbose_name='分类', null=True, on_delete=models.SET_NULL)
    tags = models.ManyToManyField('Tag', verbose_name='标签集合', blank=True)

    def __str__(self):
        return self.title

    class Meta:
        ordering = ['-last_modified_time']

    # 新增 get_absolute_url 方法
    def get_absolute_url(self):
        # 这里 reverse 解析 blog:detail 视图函数对应的 url
        return reverse('blog:detail', kwargs={'article_id': self.pk})

Django给我们提供了很多有用的字段,比如上面提到的CharFiled, TestField, DateTimeFiled等等,详情请参考官方文档。

Django中的一对多是在一中进行设置,这里对应于文章的分类,ForeignKey即数据库中的外键。on_delete=models.SET_NULL表示删除某个分类(category)后该分类下所有的Article的外键设为null(空),所以我们同时设置了null=True。多对多就不同,两边都要进行配置。详情请参考官方文档。

class Category(models.Model):
    name = models.CharField('类名', max_length=20)
    created_time = models.DateTimeField('创建时间', auto_now_add=True)
    last_modified_time = models.DateTimeField('修改时间', auto_now=True)

    def __str__(self):
        return self.name
class Tag(models.Model):
    name = models.CharField('标签名', max_length=20)
    created_time = models.DateTimeField('创建时间', auto_now_add=True)
    last_modified_time = models.DateTimeField('修改时间', auto_now=True)

    def __str__(self):
        return self.name

评论功能的实现

class BlogComment(models.Model):
    user_name = models.CharField('评论者名字', max_length=100)
    user_email = models.EmailField('评论者邮箱', max_length=255)
    body = models.TextField('评论内容')
    created_time = models.DateTimeField('评论发表时间', auto_now_add=True)
    article = models.ForeignKey('Article', verbose_name='评论所属文章', on_delete=models.CASCADE)

    def __str__(self):
        return self.body[:20]
class ArticleManage(models.Manager):
    """
    继承自默认的 Manager ,为其添加一个自定义的 archive 方法
    """
    def archive(self):
        date_list = Article.objects.datetimes('created_time', 'month', order='DESC')
        # 获取到降序排列的精确到月份且已去重的文章发表时间列表
        # 并把列表转为一个字典,字典的键为年份,值为该年份下对应的月份列表
        date_dict = defaultdict(list)
        for d in date_list:
            date_dict[d.year].append(d.month)
        # 模板不支持defaultdict,因此我们把它转换成一个二级列表,由于字典转换后无序,因此重新降序排序
        return sorted(date_dict.items(), reverse=True)

我们首先要在project_name/settings.py中配置好相应的配置文件

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', 
        'NAME': 'DB_NAME',
        'USER': 'DB_USER',
        'PASSWORD': 'DB_PASSWORD',
        'HOST': 'localhost',   # Or an IP Address that your DB is hosted on
        'PORT': '3306',
    }
}

定义完毕后,我们执行下面的命令就在数据库中可以生成相应的数据表:

$ python manage.py makemigrations

$ python manage.py migrate

admins.py

参考Mozila的教程以及结合官方文档。

views.py

下面要使用markdown2,所以在INSTALLED_APP里面要添加markdown2,不过这个mardown解析非常的不好,并且弄完还要去下载相应的markdown的css文件,有个专门的网站。

from blog.models import Article, Tag, Category
from django.views.generic import ListView, DetailView
import markdown2

class IndexView(ListView):
    # template_name属性用于指定使用哪个模板进行渲染
    template_name = "blog/index.html"

    # context_object_name属性用于给上下文变量取名(在模板中使用该名字)
    context_object_name = "article_list"

    def get_queryset(self):
        article_list = Article.objects.filter(status='p')
        for article in article_list:
            article.body = markdown2.markdown(article.body, )
        return article_list

    def get_context_data(self, **kwargs):
        kwargs['category_list'] = Category.objects.all().order_by('name')
        # 调用 archive 方法,把获取的时间列表插入到 context 上下文中以便在模板中渲染
        kwargs['date_archive'] = Article.objects.archive()
        kwargs['tag_list'] = Tag.objects.all().order_by('name')
        return super(IndexView, self).get_context_data(**kwargs)

上面因为我们要进行markdown处理,所以重新自定义了get_queryset,如果不要进行相应的处理,直接制定model就行了,get_context_data可以添加一些额外的字段,比如以后我们要在首页的侧边栏显示目录和标签,所以这里要添加一个category_listtag_list

class ArticleDetailView(DetailView):
    model = Article
    template_name = "blog/detail.html"
    context_object_name = "article"
    # pk_url_kwarg会自动和model中相应的主键对应,aritlce_id就是下面配置的URLCONF
    pk_url_kwarg = 'article_id'

    # 为了让文章以markdown形式展现,我们重写get_object()方法
    def get_object(self):
        obj = super(ArticleDetailView, self).get_object()
        obj.body = markdown2.markdown(obj.body)
        return obj
        
    # 新增 form 到 context
    def get_context_data(self, **kwargs):
        kwargs['comment_list'] = self.object.blogcomment_set.all()
        kwargs['form'] = BlogCommentForm()
        return super(ArticleDetailView, self).get_context_data(**kwargs)
class CategoryView(ListView):
    template_name = "blog/index.html"
    context_object_name = "article_list"
    
    def get_queryset(self):
        # url里的cate_id传递给CategoryView,传递的参数在kwargs属性中获取
        article_list = Article.objects.filter(category=self.kwargs['cate_id'],status='p')
        for article in article_list:
            article.body = markdown2.markdown(article.body, )
        return article_list

    def get_context_data(self, **kwargs):
        # 增加一个category_list,用于在页面显示所有分类,按照名字排序
        kwargs['category_list'] = Category.objects.all().order_by('name')
        return super(CategoryView, self).get_context_data(**kwargs)
class TagView(ListView):
    template_name = "blog/index.html"
    context_object_name = "article_list"

    def get_queryset(self):
        """
        根据指定的标签获取该标签下的全部文章
        """
        article_list = Article.objects.filter(tags=self.kwargs['tag_id'], status='p')
        for article in article_list:
            article.body = markdown2.markdown(article.body, extras=['fenced-code-blocks'], )
        return article_list

    def get_context_data(self, **kwargs):
        kwargs['tag_list'] = Tag.objects.all().order_by('name')
        return super(TagView, self).get_context_data(**kwargs)
from django.views.generic.edit import FormView

class CommentPostView(FormView):
    form_class = BlogCommentForm
    template_name = 'blog/detail.html' 

    def form_valid(self, form):
        target_article = get_object_or_404(Article, pk=self.kwargs['article_id'])
        # 调用ModelForm的save方法保存评论,设置commit=False则先不保存到数据库,
        # 而是返回生成的comment实例,直到真正调用save方法时才保存到数据库。
        comment = form.save(commit=False)
        # 把评论和文章关联
        comment.article = target_article
        comment.save()
        # 评论生成成功,重定向到被评论的文章页面,get_absolute_url 请看下面的讲解。
        self.success_url = target_article.get_absolute_url()
        return HttpResponseRedirect(self.success_url)

    def form_invalid(self, form):
        target_article = get_object_or_404(Article, pk=self.kwargs['article_id'])

        # 不保存评论,回到原来提交评论的文章详情页面
        return render(self.request, 'blog/detail.html', {
            'form': form,
            'article': target_article,
            'comment_list': target_article.blogcomment_set.all(),
        })

template

{% for %}循环标签,{% if %}判断标签. {{ variable }}是一些非常常用的标签

在模板文件中我们可以这样使用,views.py中已经指定了context_object_name = "article_list",并且已经在get_queryset()中进行了markdown处理

{% for article in article_list %}
    {{article.title}}

通常都会设置一个通用的父模板:

{% extends "base_generic.html" %}

{% block content %}
...
{% endblock %}

好像要这么这么设置:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'blog/templates')]
        ,
        'APP_DIRS': True,
...
]

静态文件

由于源代码丢失,具体情况记得不太清晰,静态文件路径要设置好,如果js文件加载异常,可能是加载顺序的问题。

base_generic.html大概就是下面这样的格式:

nbsp;html>
{% load staticfiles %}


    <meta>
    <title>Myblog</title>
    <link>
    <link>
    <link>

...

下面这样设置貌似有点问题:

# mysite/settings.py
STATIC_URL = '/static/'
STATICFILES = os.path.join(BASE_DIR, 'blog/static')

具体参考官方文档

部署

使用uwsgi+nginx

/etc/nginx/sites-available/mysite.conf,blog是app名字,static文件放在了下面,建议直接放在mysite下面,template也是一样:

server {
    listen 80;

    location /static/ {
        alias /home/omrsf/mysite/blog/static/;
    }

    location / {
        uwsgi_pass 127.0.0.1:8001;
        include     /etc/nginx/uwsgi_params;
    }
}

uwsgi -i uwsgi.ini来启动uwsgi进程,结合nohup &amp;

[uwsgi]
socket = 127.0.0.1:8001
chdir=/home/ormsf/mysite/
wsgi-file = mysite/wsgi.py

processes = 2
threads = 4

chmod-socket = 664
クラスベースのビュー

rrreee

別のURLconfを含める

rrreeerrreee

Use (?P< ;>d+) のパラメータに値をキャプチャします (?Pd+)。/blog/article/3 にアクセスすると、3 がarticle_id にキャプチャされ、この値はviews.ArticleDetailView に渡されます。

rrreee

namespace パラメーターは名前空間を指定します。つまり、urls.py の URL はブログ アプリの下にあるため、異なるアプリに同じ URL があっても競合は発生しません。

ユーザーが特定の記事にアクセスしたいとすると、blog:detail ビュー関数に対応する URL が自動的に解析され、article.pk (記事の主キー) が詳細ビュー関数 details に渡されます。 は、blog/urls.py で指定された name です。
    rrreee
  • ディレクトリにアクセスしたい場合は

    rrreee

    models.py
  • django.db.models が orm フレームワークの基礎であり、blog/models に新しいディレクトリを作成します。 py 3 つのモデル: ArticleCategoryTag

    rrreee

    Django は、上記の CharFiledTestFieldDateTimeFiled など、多くの便利なフィールドを提供します。詳細については、公式ドキュメントを参照してください。
Django の 1 対多は記事の分類に対応する 1 つに設定されており、ForeignKey はデータベース内の外部キーです。 on_delete=models.SET_NULL というのは、カテゴリ(category)を削除した後、そのカテゴリ配下のすべてのArticleの外部キーがnull(空)に設定されるという意味なので、同時にnull=Trueを設定します。多対多は異なり、両方の側で構成する必要があります。詳細については公式ドキュメントを参照してください。

rrreeerrreee

コメント機能の実装

rrreeerrreee

まずproject_name/settings.pyで対応する設定ファイルを設定する必要があります

rrreee

定義が完了したら、次のコマンドにより、データベースに対応するデータ テーブルを生成できます:

rrreee

admins.py

Mozila のチュートリアルと公式ドキュメントを参照してください。

views.py🎜🎜以下ではmarkdown2を使用するので、INSTALLED_APPにmarkdown2を追加する必要があります。ただし、このmardown解析は非常に悪いので、終了後に対応するmarkdown cssファイルをダウンロードする必要があります。 Webサイト。 🎜rrreee🎜マークダウン処理を行う必要があるため、get_queryset を再定義しました。対応する処理を実行したくない場合は、get_context_data追加のフィールドを追加できます。たとえば、将来的にはホームページのサイドバーにディレクトリとタグを表示するため、<code>category_listtag_list を追加する必要があります。コード>こちら。 🎜rrreeerrreeerreerrreee🎜template🎜🎜<code>{% for %} ループ タグ、{% if %} 決定タグ {{ variable }} などがあります。非常に一般的に使用されるタグ 🎜🎜 は、テンプレート ファイル内でこのように使用できます。 context_object_name = "article_list" は、views.py で指定され、get_queryset() で実行されます。マークダウン処理🎜rrreee🎜は、通常、共通の親テンプレートを設定します: 🎜rrreee🎜 次のように設定されるようです: 🎜rrreee🎜 静的ファイル🎜🎜 ソースコードが紛失しているため、具体的な状況をはっきりと覚えていませんが、静的ファイルファイルパスを正しく設定する必要があります。js ファイルが異常に読み込まれる場合は、読み込み順序に問題がある可能性があります。 🎜🎜base_generic.html はおそらく次の形式になっています: 🎜rrreee🎜以下の設定に問題があるようです: 🎜rrreee🎜詳細は公式ドキュメントを参照してください🎜🎜Deployment🎜🎜Use uwsgi+nginx🎜🎜/etc /nginx/sites-available/mysite .conf、blog はアプリの名前であり、静的ファイルは mysite の直下に配置することをお勧めします: 🎜rrreee🎜 uwsgi -i uwsgi.ini を使用して uwsgi プロセスを開始し、nohup &amp; と組み合わせます。 🎜rrreee🎜改善点🎜🎜 現在の記事では、モデルを admin.py に直接登録してから、管理バックグラウンドで公開し、API インターフェイスとオンライン エディターにすることができます。基本的なユーザー認証機能を追加します。 🎜🎜断片的な知識ポイント🎜🎜 null と空白の違い🎜🎜🎜🎜null はデータベースに関するもので、null=True の場合、データベースのフィールドが空であってもよいことを意味します。 🎜🎜🎜🎜blank はフォーム用です。blank=True の場合、管理インターフェイスでモデル レコードを追加するときなど、フォームに入力するときにこのフィールドに入力する必要がないことを意味します。直感的にわかるのは、フィールドが太字ではないということです。 🎜🎜🎜🎜render と render_response🎜🎜 まず render を使用します。 🎜🎜get_absolute_url🎜🎜モデルには get_absolute_url があり、reverse と組み合わせることができます。 🎜🎜その他の Python-Django 関連記事については、PHP 中国語 Web サイトに注目してください。 🎜🎜🎜
声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
Pythonと時間:勉強時間を最大限に活用するPythonと時間:勉強時間を最大限に活用するApr 14, 2025 am 12:02 AM

限られた時間でPythonの学習効率を最大化するには、PythonのDateTime、時間、およびスケジュールモジュールを使用できます。 1. DateTimeモジュールは、学習時間を記録および計画するために使用されます。 2。時間モジュールは、勉強と休息の時間を設定するのに役立ちます。 3.スケジュールモジュールは、毎週の学習タスクを自動的に配置します。

Python:ゲーム、GUIなどPython:ゲーム、GUIなどApr 13, 2025 am 12:14 AM

PythonはゲームとGUI開発に優れています。 1)ゲーム開発は、2Dゲームの作成に適した図面、オーディオ、その他の機能を提供し、Pygameを使用します。 2)GUI開発は、TKINTERまたはPYQTを選択できます。 TKINTERはシンプルで使いやすく、PYQTは豊富な機能を備えており、専門能力開発に適しています。

Python vs. C:比較されたアプリケーションとユースケースPython vs. C:比較されたアプリケーションとユースケースApr 12, 2025 am 12:01 AM

Pythonは、データサイエンス、Web開発、自動化タスクに適していますが、Cはシステムプログラミング、ゲーム開発、組み込みシステムに適しています。 Pythonは、そのシンプルさと強力なエコシステムで知られていますが、Cは高性能および基礎となる制御機能で知られています。

2時間のPython計画:現実的なアプローチ2時間のPython計画:現実的なアプローチApr 11, 2025 am 12:04 AM

2時間以内にPythonの基本的なプログラミングの概念とスキルを学ぶことができます。 1.変数とデータ型、2。マスターコントロールフロー(条件付きステートメントとループ)、3。機能の定義と使用を理解する4。

Python:主要なアプリケーションの調査Python:主要なアプリケーションの調査Apr 10, 2025 am 09:41 AM

Pythonは、Web開発、データサイエンス、機械学習、自動化、スクリプトの分野で広く使用されています。 1)Web開発では、DjangoおよびFlask Frameworksが開発プロセスを簡素化します。 2)データサイエンスと機械学習の分野では、Numpy、Pandas、Scikit-Learn、Tensorflowライブラリが強力なサポートを提供します。 3)自動化とスクリプトの観点から、Pythonは自動テストやシステム管理などのタスクに適しています。

2時間でどのくらいのPythonを学ぶことができますか?2時間でどのくらいのPythonを学ぶことができますか?Apr 09, 2025 pm 04:33 PM

2時間以内にPythonの基本を学ぶことができます。 1。変数とデータ型を学習します。2。ステートメントやループの場合などのマスター制御構造、3。関数の定義と使用を理解します。これらは、簡単なPythonプログラムの作成を開始するのに役立ちます。

プロジェクトの基本と問題駆動型の方法で10時間以内にコンピューター初心者プログラミングの基本を教える方法は?プロジェクトの基本と問題駆動型の方法で10時間以内にコンピューター初心者プログラミングの基本を教える方法は?Apr 02, 2025 am 07:18 AM

10時間以内にコンピューター初心者プログラミングの基本を教える方法は?コンピューター初心者にプログラミングの知識を教えるのに10時間しかない場合、何を教えることを選びますか...

中間の読書にどこでもfiddlerを使用するときにブラウザによって検出されないようにするにはどうすればよいですか?中間の読書にどこでもfiddlerを使用するときにブラウザによって検出されないようにするにはどうすればよいですか?Apr 02, 2025 am 07:15 AM

fiddlereveryversings for the-middleの測定値を使用するときに検出されないようにする方法

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

AtomエディタMac版ダウンロード

AtomエディタMac版ダウンロード

最も人気のあるオープンソースエディター

VSCode Windows 64 ビットのダウンロード

VSCode Windows 64 ビットのダウンロード

Microsoft によって発売された無料で強力な IDE エディター

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

DVWA

DVWA

Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、