摘要:使用的形式捕獲值給中得參數,比如,當訪問時,將會將捕獲給這個值會傳到。表示刪除某個分類后該分類下所有的的外鍵設為空,所以我們同時設置了。多對多就不同,兩邊都要進行配置。增加基本的用戶認證功能。
準備工作
新建一個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
一般在urls.py中配置url,在models.py中配置model,在views.py中配置View。
urls.pyFunction 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/(?Pd+)$", views.ArticleDetailView.as_view(), name="detail"), url(r"^blog/category/(?P d+)$", views.CategoryView.as_view(), name="category"), url(r"^blog/tag/(?P d+)$", views.TagView.as_view(), name="tag"), ]
使用(?P<>d+)的形式捕獲值給<>中得參數,比如(?P
# 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。
{{ article.title }}
如果要訪問某個目錄
{{ category.name }}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 migrateadmins.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_list和tag_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大概就是下面這樣的格式:
{% load staticfiles %}Myblog ...
下面這樣設置貌似有點問題:
# 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 &:
[uwsgi] socket = 127.0.0.1:8001 chdir=/home/ormsf/mysite/ wsgi-file = mysite/wsgi.py processes = 2 threads = 4 chmod-socket = 664改進
目前文章是直接在admin.py中注冊model,然后去admin后臺發布的,可以做成api接口,做一個在線的編輯器。增加基本的用戶認證功能。
零碎知識點 null和blank的區別null 是針對數據庫而言,如果 null=True, 表示數據庫的該字段可以為空。
blank 是針對表單的,如果 blank=True,表示你的表單填寫該字段的時候可以不填,比如 admin 界面下增加 model 一條記錄的時候。直觀的看到就是該字段不是粗體。
render與render_response優先采用render。
get_absolute_urlmodel有一個get_absolute_url,它可以與reverse結合起來。
參考資料GitHub項目地址
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/38365.html
摘要:這里使用版本如果你使用是版本需將相關命令中的替換成替換成以及注意其它版本查差異性安裝安裝安裝查看版本創建項目為項目名創建數據庫默認使用如果使用其它數據庫請配置相關設置文件查看項目開啟自帶的小型開發服務器為可選配置,不指定的話默認為開 這里使用python3版本 如果你使用是python2.7版本 需將相關命令中的python3替換成python;pip3替換成pip;以及注意其它版本查...
摘要:項目地址部署的方案都在腳本里頭,說明如下使用方法版本簡單介紹是一個利用轉發操作系統中部署的基于框架和框架以及一個的服務。個服務是部署在環境中,通過和進行發送和接收消息。在前臺以及整個主要利用去操作。 項目地址:https://github.com/yuyangit/BMProject 部署的方案都在腳本里頭,說明如下: BMPlatform使用方法 版本 v0.2 1.簡單介紹...
摘要:項目地址部署的方案都在腳本里頭,說明如下使用方法版本簡單介紹是一個利用轉發操作系統中部署的基于框架和框架以及一個的服務。個服務是部署在環境中,通過和進行發送和接收消息。在前臺以及整個主要利用去操作。 項目地址:https://github.com/yuyangit/BMProject 部署的方案都在腳本里頭,說明如下: BMPlatform使用方法 版本 v0.2 1.簡單介紹...
摘要:靜態資源路徑可以有多個,所以這里使用一個列表進行配置再次進入,完美后記現在只涉及到了項目的配置和一些基礎的配置,沒有涉及到請求從開始到完成的任何內容。下篇教程將集中進行記錄。 前言 推薦使用 virtualenv 創建 python 虛擬環境,防止因為使用 pip 安裝依賴到全局引起版本沖突的問題,PyCharm 默認會生成一個 venv 目錄并創建虛擬環境,使用 IDE 自帶的終端...
閱讀 3722·2021-11-23 09:51
閱讀 1386·2021-11-10 14:35
閱讀 4025·2021-09-22 15:01
閱讀 1293·2021-08-19 11:12
閱讀 392·2019-08-30 15:53
閱讀 1704·2019-08-29 13:04
閱讀 3441·2019-08-29 12:52
閱讀 3069·2019-08-23 16:14