checklist-seo 0.0.7
The full checklist to provide tools inside Django in order to write right content
License: MIT
Requires Python: >=3.7

<h1>Check list SEO <img alt="Build" src="https://travis-ci.org/itarverne/checklist-seo.svg?branch=master"></h1>
<p><img alt="" src="./static/images/seo_logo.png"></p>
<p><a href="https://codeclimate.com/github/itarverne/checklist-seo/maintainability" rel="nofollow"><img alt="Maintainability" src="https://api.codeclimate.com/v1/badges/1ea9094958cb77a0c1a9/maintainability"></a>
<a href="https://codeclimate.com/github/itarverne/checklist-seo/test_coverage" rel="nofollow"><img alt="Test Coverage" src="https://api.codeclimate.com/v1/badges/1ea9094958cb77a0c1a9/test_coverage"></a></p>
<h1>Features</h1>
<ul>
<li>Keyword repartition</li>
<li>Length content</li>
<li>Check title article length</li>
<li>Url is optimized</li>
<li>Number internal Links</li>
</ul>
<h1>Installation</h1>
<h2>Pypi</h2>
<p><a href="https://pypi.org/project/checklist-seo/" rel="nofollow"><img alt="PyPI version" src="https://img.shields.io/pypi/v/checklist-seo"></a></p>
<p><code>pip install checklist-seo</code></p>
<h2>Installing the application in Django</h2>
<p>To use this application, you need first to add it to your config file.</p>
<p>In your config file (ex: settings.py):</p>
<pre><code># Application definition

INSTALLED_APPS = [
	...
	'seo'
	...
]
</code></pre>
<h2>SEO Pannel</h2>
<p>To setup the keyword for SEO, you need to add a special SEO Pannel that will appear in your page creation in wagtail admin.</p>
<p>The module contains a model in models/SeoPage, the model need to be used as a base for your page models.</p>
<p>Example of your model:</p>
<pre><span class="k">class</span> <span class="nc">HomePage</span><span class="p">(</span><span class="n">SeoPage</span><span class="p">):</span>
    <span class="n">date</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">DateField</span><span class="p">(</span><span class="s2">&quot;Post date&quot;</span><span class="p">)</span>
    <span class="n">intro</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">max_length</span><span class="o">=</span><span class="mi">250</span><span class="p">)</span>
    <span class="n">delay</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">IntegerField</span><span class="p">(</span><span class="n">default</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">validators</span><span class="o">=</span><span class="p">[</span><span class="n">MaxValueValidator</span><span class="p">(</span><span class="mi">99</span><span class="p">),</span> <span class="n">MinValueValidator</span><span class="p">(</span><span class="mi">0</span><span class="p">)])</span>
    <span class="n">body</span> <span class="o">=</span> <span class="n">StreamField</span><span class="p">([</span>
        <span class="p">(</span><span class="s1">&#39;text&#39;</span><span class="p">,</span> <span class="n">RichTextBlock</span><span class="p">(</span><span class="n">blank</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">features</span><span class="o">=</span><span class="p">[</span><span class="s1">&#39;h2&#39;</span><span class="p">,</span> <span class="s1">&#39;h3&#39;</span><span class="p">,</span> <span class="s1">&#39;h4&#39;</span><span class="p">,</span> <span class="s1">&#39;bold&#39;</span><span class="p">,</span> <span class="s1">&#39;italic&#39;</span><span class="p">,</span> <span class="s1">&#39;link&#39;</span><span class="p">,</span>
                                                     <span class="s1">&#39;code&#39;</span><span class="p">,</span> <span class="s1">&#39;ol&#39;</span><span class="p">,</span> <span class="s1">&#39;ul&#39;</span><span class="p">,</span> <span class="s1">&#39;hr&#39;</span><span class="p">,</span> <span class="s1">&#39;document-link&#39;</span><span class="p">,</span> <span class="s1">&#39;image&#39;</span><span class="p">,</span> <span class="s1">&#39;embed&#39;</span><span class="p">,</span> <span class="s1">&#39;superscript&#39;</span><span class="p">,</span> <span class="s1">&#39;subscript&#39;</span><span class="p">,</span> <span class="s1">&#39;strikethrough&#39;</span><span class="p">,</span> <span class="s1">&#39;blockquote&#39;</span><span class="p">])),</span>
        <span class="p">(</span><span class="s1">&#39;rawHtml&#39;</span><span class="p">,</span> <span class="n">RawHTMLBlock</span><span class="p">(</span><span class="n">blank</span><span class="o">=</span><span class="kc">True</span><span class="p">)),</span>
    <span class="p">],</span> <span class="n">blank</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
    <span class="n">images_keyword</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">max_length</span><span class="o">=</span><span class="mi">250</span><span class="p">,</span> <span class="n">blank</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
    <span class="n">selected_image</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">ForeignKey</span><span class="p">(</span>
        <span class="s1">&#39;wagtailimages.Image&#39;</span><span class="p">,</span>
        <span class="n">null</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
        <span class="n">blank</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
        <span class="n">on_delete</span><span class="o">=</span><span class="n">models</span><span class="o">.</span><span class="n">SET_NULL</span><span class="p">,</span>
        <span class="n">related_name</span><span class="o">=</span><span class="s1">&#39;+&#39;</span>
    <span class="p">)</span>

    <span class="n">keep_slug</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">BooleanField</span><span class="p">(</span>
        <span class="n">verbose_name</span><span class="o">=</span><span class="p">(</span><span class="s1">&#39;Keep current slug&#39;</span><span class="p">),</span>
        <span class="n">default</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
        <span class="n">help_text</span><span class="o">=</span><span class="p">(</span><span class="s2">&quot;Keep current slug or save to generate a new slug.&quot;</span><span class="p">)</span>
    <span class="p">)</span>

    <span class="k">def</span> <span class="nf">_get_autogenerated_slug</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">base_slug</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Redefinition of wagtail&#39;s _get_autogenerated_slug so you can use your own slug generator.&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">slug</span>

    <span class="n">search_fields</span> <span class="o">=</span> <span class="n">Page</span><span class="o">.</span><span class="n">search_fields</span> <span class="o">+</span> <span class="p">[</span>
        <span class="n">index</span><span class="o">.</span><span class="n">SearchField</span><span class="p">(</span><span class="s1">&#39;intro&#39;</span><span class="p">),</span>
    <span class="p">]</span>

    <span class="n">content_panels</span> <span class="o">=</span> <span class="n">Page</span><span class="o">.</span><span class="n">content_panels</span> <span class="o">+</span> <span class="p">[</span>
        <span class="n">MultiFieldPanel</span><span class="p">([</span>
            <span class="n">FieldPanel</span><span class="p">(</span><span class="s1">&#39;date&#39;</span><span class="p">),</span>
            <span class="n">FieldRowPanel</span><span class="p">([</span>
                <span class="n">FieldPanel</span><span class="p">(</span><span class="s1">&#39;delay&#39;</span><span class="p">),</span>
            <span class="p">]),</span>
        <span class="p">],</span> <span class="n">heading</span><span class="o">=</span><span class="s2">&quot;Blog information&quot;</span><span class="p">),</span>
        <span class="n">FieldPanel</span><span class="p">(</span><span class="s1">&#39;intro&#39;</span><span class="p">),</span>
        <span class="n">StreamFieldPanel</span><span class="p">(</span><span class="s1">&#39;body&#39;</span><span class="p">),</span>
        <span class="n">FieldRowPanel</span><span class="p">([</span>
            <span class="n">FieldPanel</span><span class="p">(</span><span class="s1">&#39;images_keyword&#39;</span><span class="p">),</span>
        <span class="p">],</span> <span class="n">heading</span><span class="o">=</span><span class="s2">&quot;Images&quot;</span><span class="p">),</span>
        <span class="n">ImageChooserPanel</span><span class="p">(</span><span class="n">field_name</span><span class="o">=</span><span class="s2">&quot;selected_image&quot;</span><span class="p">,</span> <span class="n">heading</span><span class="o">=</span><span class="s2">&quot;Image sélectionnée&quot;</span><span class="p">),</span>
    <span class="p">]</span>

    <span class="n">promote_panels</span> <span class="o">=</span> <span class="p">[</span>
        <span class="n">MultiFieldPanel</span><span class="p">([</span>
            <span class="n">FieldPanel</span><span class="p">(</span><span class="s1">&#39;slug&#39;</span><span class="p">),</span>
            <span class="n">FieldPanel</span><span class="p">(</span><span class="s1">&#39;keep_slug&#39;</span><span class="p">),</span>
            <span class="n">FieldPanel</span><span class="p">(</span><span class="s1">&#39;seo_title&#39;</span><span class="p">),</span>
            <span class="n">FieldPanel</span><span class="p">(</span><span class="s1">&#39;show_in_menus&#39;</span><span class="p">),</span>
            <span class="n">FieldPanel</span><span class="p">(</span><span class="s1">&#39;search_description&#39;</span><span class="p">),</span>
        <span class="p">],</span> <span class="n">heading</span><span class="o">=</span><span class="s2">&quot;Common Page Configuration&quot;</span><span class="p">),</span>
    <span class="p">]</span>

    <span class="n">edit_handler</span> <span class="o">=</span> <span class="n">TabbedInterface</span><span class="p">([</span>
        <span class="n">ObjectList</span><span class="p">(</span><span class="n">content_panels</span><span class="p">,</span> <span class="n">heading</span><span class="o">=</span><span class="s1">&#39;Content&#39;</span><span class="p">),</span>
        <span class="n">ObjectList</span><span class="p">(</span><span class="n">promote_panels</span><span class="p">,</span> <span class="n">heading</span><span class="o">=</span><span class="s2">&quot;Promote&quot;</span><span class="p">),</span>
        <span class="n">SeoPage</span><span class="o">.</span><span class="n">seo_object_list</span><span class="p">,</span>
        <span class="n">ObjectList</span><span class="p">(</span><span class="n">Page</span><span class="o">.</span><span class="n">settings_panels</span><span class="p">,</span> <span class="n">heading</span><span class="o">=</span><span class="s1">&#39;Settings&#39;</span><span class="p">)</span>
    <span class="p">])</span>
</pre>
<h2>Routing</h2>
<p>In your routing projet file <code>urls.py</code></p>
<pre><span class="kn">from</span> <span class="nn">django.conf.urls</span> <span class="kn">import</span> <span class="n">url</span>
<span class="kn">from</span> <span class="nn">django.urls</span> <span class="kn">import</span> <span class="n">include</span>

<span class="n">urlpatterns</span> <span class="o">=</span> <span class="p">[</span>
    <span class="o">...</span>
    <span class="n">url</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;^seo/&#39;</span><span class="p">,</span> <span class="n">include</span><span class="p">(</span><span class="s1">&#39;seo.urls&#39;</span><span class="p">),</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;seo&#39;</span><span class="p">),</span>
<span class="p">]</span>
</pre>
<h2>Static</h2>
<p>To get the CSS / JS / Image file from this app to your projet
<code>python manage.py collectstatic</code></p>
<h2>DB Migration</h2>
<p>Now you can detect the change
<code>python manage.py makemigrations</code></p>
<p>And apply it on DB
<code>python manage.py migration</code></p>
<h2>Test</h2>
<p><code>pytest</code></p>