Django developer usefulness

Foreword

To write this article, a very large layer of material was studied, scattered all over the Internet, in forums, chats, blog sites, stackoverflow. I put it all together, as it will be useful to me and I really hope that other Django developers will also be happy with this material. If there is anything to add (improve) or correct, please write in the comments or in Dialogues (private messages) Habr.





Handler 404 testing

If we try to test the 404 error with the given debug = True, then we will receive a standard Django error report indicating the reason, but using the following method you can check that the 404 error is working without unnecessary worries. On a working site, I highly recommend using nginx.





  1. Open for editing the settings.py file located in the project directory and set the value debug = False





  2. In the same directory, open the urls.py file for editing and add the following lines:





from django.urls import re_path
from django.views.static import serve #  

re_path(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),

re_path(r'^static/(?P<path>.*)$', serve, {'document_root': settings.STATIC_ROOT}),
      
      



debug false, , , django nginx, , , 404 Django localhost, python manage.py runserver .





, , Python/Django      ,   .

( :

: habrhabr

: pp#6JZ2\a7y=





: , . 





, Worker - FK Experience:





class Worker(models.Model):
    public_cv = models.BooleanField(default=False, verbose_name='Can everyone see your resume ?')
    cv_name = models.CharField(max_length=250, verbose_name='CV name', blank=True)
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name='Author', default=0)
	
	# +  

    def __str__(self):
        return self.name

    def publish(self):
        self.published_date = timezone.now()
        self.save()

class Experience(models.Model):
    worker = models.ForeignKey(Worker, on_delete=models.CASCADE)
    title = models.CharField(max_length=200, verbose_name='Position name')

	# +  

    def __str__(self):
        return self.title

    def publish(self):
        self.published_date = timezone.now()
        self.save()

# +  
      
      



, - django-admin, StackedInline:





class ExperienceInstance(admin.StackedInline):
    model = Experience
    extra = 1

@admin.register(Worker)
class PublishWorkers(admin.ModelAdmin):
    inlines = [
        ExperienceInstance,]
      
      



Django-admin, Experience Worker " Experience":





views.py , Experience Experience, Formset:





from django.forms import inlineformset_factory
from django.http import HttpResponseRedirect
from .forms import ExperienceForm


def expformview(request, worker_uid):
    worker = Worker.objects.get(uid=worker_uid)
    ExperienceFormset = inlineformset_factory(
        Worker, Experience, form=ExperienceForm, extra=1, max_num=15, can_delete=True
    )
    if request.method == 'POST':
        formset = ExperienceFormset(request.POST, instance=worker)
        if formset.is_valid():
            formset.save()
            return HttpResponseRedirect(request.META.get('HTTP_REFERER'))

    formset = ExperienceFormset(instance=worker)
    return render(request, 'site/expform.html',
                  {
                      'formset': formset,
                      'worker': worker,
                  }
                  )
      
      



, forms.py ExperienceForm:





class ExperienceForm(forms.ModelForm):
    started = forms.DateField(
        required=False,
        label='Start date',
        widget=forms.TextInput(attrs={'placeholder': 'YYYY-MM-DD'})
    )
    ended = forms.DateField(
        required=False,
        label='End date',
        widget=forms.TextInput(attrs={'placeholder': 'YYYY-MM-DD'})
    )

    class Meta:
        model = Experience
        fields = ('title',
                  'selfedu',
                  )
      
      



HTML. Crispy . {{formset.media}}



WYSIWYG- ckeditor. type="submit"



, :





HTML
{% extends 'site/base.html' %}
{% load crispy_forms_tags %}
{% block content %}
{% if worker.author == request.user%}
<html lang="en">
   <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Experience | {{worker}}</title>
   </head>
   <body>
      <center>
         <div class="col-lg-5" style="margin:1em;">
            <nav aria-label="breadcrumb">
               <ol class="breadcrumb">
                   <li class="breadcrumb-item">Basic information</li>
                   <li class="breadcrumb-item active" aria-current="page"><b>Experience</b></li>
                   <li class="breadcrumb-item">Education</li>
                   <li class="breadcrumb-item">Certification</li>
                   <li class="breadcrumb-item">Awards</li>
                   <li class="breadcrumb-item">Projects</li>
               </ol>
            </nav>
         </div>
      </center>
   <h2 align="center" style="margin:1em;">{{worker}}'s Experience form</h2>
      <form method="post">
         {% csrf_token %}
         <div class="row" style="margin:2em 0 2em 0;">
            <div class="col-lg-5 mx-auto">
               {{formset.media}}
               {{formset|crispy}}
            </div>
             <div class="col-lg-12">
                 <center><button type="submit" class="btn btn-outline-warning">Save & Add</button>
                 <a href="edu"><button type="button" class="btn btn-outline-success">Next > Education</button></a></center>
             </div>
         </div>
      </form>
   </body>
</html>
{%else%}
      <div class="row">
         <div class="col-lg-12" style="margin-top:6em;">
            <center>
               <h2>You have not access to this section</h2>
            </center>
         </div>
      </div>
      {%endif%}
{% endblock %}
      
      



:





PDF ( )

, HTML PDF  XHTML2PDF; venv :





pip install xhtml2pdf
      
      



views.py:





from xhtml2pdf import pisa

def render_pdf_view(request, worker_uid):
    template_path = 'site/pdf.html'
    worker = Worker.objects.get(uid=worker_uid)
    exp = Experience.objects.filter(worker=worker)
    context = {
        'worker': worker,
        'exp': exp,
    }
    response = HttpResponse(content_type='application/pdf')

    response['Content-Disposition'] = 'filename="%s_%s.pdf"' % (worker.name, worker.created_date.strftime('%Y-%m-%d')) #     PDF : _--
    #     
    template = get_template(template_path)
    html = template.render(context)

    #  PDF
    pisa_status = pisa.CreatePDF(html, dest=response, )
    #  
    if pisa_status.err:
        return HttpResponse('We had some errors <pre>' + html + '</pre>')
    return response
      
      



HTML , , PDF , <style></style>



.





To Russian characters are correctly displayed in the exported PDF you want to download a font that supports the Cyrillic (Russian) letters, and put it in the static / fonts /, at the same time indicate to-text file full path in view of system directories, such as in my case, the path looks like this:  /var/www/cvmaker/static/fonts/arial.ttf



, and <style/>



add the following between the tags :





@font-face {
         font-family: 'sans-serif';
         src: url("/var/www/cvmaker/static/fonts/arial.ttf");
         }
         body{
         font-family: "sans-serif";
         }
      
      



Thus, in the exported PDF file, instead of black squares in place of Russian letters, we see normal Cyrillic characters:








All Articles