Avant-propos
Pour rédiger cet article, une très grande couche de matériel a été étudiée, dispersée sur Internet, dans les forums, chats, sites de blogs, stackoverflow. J'ai tout rassemblé, car cela me sera utile et j'espère vraiment que d'autres développeurs Django seront également satisfaits de ce matériel. S'il y a quelque chose à ajouter (améliorer) ou corriger, veuillez écrire dans les commentaires ou dans Dialogues (messages privés) Habr.
Test du Handler 404
Si nous essayons de tester l'erreur 404 avec le debug = True, nous recevrons un rapport d'erreur Django standard indiquant la raison, mais en utilisant la méthode suivante, vous pouvez vérifier que l'erreur 404 fonctionne sans soucis inutiles. Sur un site de travail, je recommande fortement d'utiliser nginx.
Ouvrez pour modifier le fichier settings.py situé dans le répertoire du projet et définissez la valeur debug = False
Dans le même répertoire, ouvrez le fichier urls.py pour le modifier et ajoutez les lignes suivantes:
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>
.
Pour les caractères russes sont correctement affichés dans le PDF exporté, vous souhaitez télécharger une police prenant en charge les lettres cyrilliques (russes) et la placer dans le fichier static / fonts /, en même temps indiquer le chemin complet du fichier texte en vue du système répertoires, comme dans mon cas, le chemin ressemble à ceci :, /var/www/cvmaker/static/fonts/arial.ttf
et <style/>
ajoutez ce qui suit entre les balises :
@font-face {
font-family: 'sans-serif';
src: url("/var/www/cvmaker/static/fonts/arial.ttf");
}
body{
font-family: "sans-serif";
}
Ainsi, dans le fichier PDF exporté, au lieu de carrés noirs à la place des lettres russes, nous voyons des caractères cyrilliques normaux: