📜 ⬆️ ⬇️

Some features of Django that are well known in advance

Django

Django is great. In fact: if you write about how much good has appeared in the world with the advent and development of Django, you can write for a very long time, and still not tell about everything. Personally, at the moment I have been constantly using Django for four and a half years, and all this time Django has been getting better and better.

And yet at some point you realize that not all is in the documentation. And here the solutions to the problems appear different - you can open the source code for Django, you can see what they write on Stackoverflow and in other places (mailing lists often help, as well as the official Trac), but even better - all this together.
')
Let's look at just a few examples of what may be needed in everyday work, but what (so far) you can not read in the official documentation. However, if you think you need to add something else - write, maybe this is true.

1. Select all model objects (when there are more objects than fit on one page) and administrative interface actions (admin actions) with intermediate pages (intermediate pages).

Do you have your own actions in the administrative interface? Are they using intermediate pages? If yes, then check out exactly where the queryset is taken from when displaying this very intermediate page.

Because if it is done this way (as described in the documentation ):

selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME) 

Then you will encounter the fact that the action will work, but only, for example, for the first 100 objects (if 100 are displayed on their page), and not for all objects of the model, as was chosen.

In fact, usually on an intermediate page, a form is displayed that contains hidden fields (“_selected_action”) with object numbers.

That is (in ModelAdmin):

  class AssignBooksForm(forms.Form): _selected_action = forms.CharField(widget=forms.MultipleHiddenInput) user = forms.ModelChoiceField(queryset=User.objects.all(), label=u"", empty_label=None) def assign_books(self, request, queryset): form = None if 'cancel' in request.POST: self.message_user(request, u'  .') return elif 'assign' in request.POST: form = self.AssignBooksForm(request.POST) if form.is_valid(): user = form.cleaned_data['user'] for book in queryset: assign_book(book.pk, user.pk) self.message_user(request, u'  (%s)   %s.' % (queryset.count(), user.username)) return HttpResponseRedirect(request.get_full_path()) if not form: form = self.AssignBooksForm(initial={'_selected_action': queryset.values_list('os_id', flat=True)}) return render_to_response('books/assign_books.html', {'books': queryset, 'form': form, 'path':request.get_full_path()}, context_instance=RequestContext(request)) assign_books.short_description = u'  ' actions = ['assign_books'] 

But the probability is really great that instead of this line:

 form = self.AssignBooksForm(initial={'_selected_action': queryset.values_list('id', flat=True)}) 

Such a line (for example, here ):

 form = self.AssignBooksForm(initial={'_selected_action': request.POST.getlist(admin.ACTION_CHECKBOX_NAME)}) 

And in this case it turns out especially interesting. Because when the user selected all objects (checked the box to the left of the column names, and then clicked “Select all ... (...)” above the table with the list of records), JS indicated the value 1 for the hidden field “select_across”. After that, ModelAdmin.response_action ( contrib.admin.options), finding that the form (contrib.admin.helpers.ActionForm) is set to select_across (BooleanField), does not limit the queryset to those objects that are checked, but calls the action function with the full queryset (but the contents of the request object, the response_action method does not change, of course).

And if you have something like this displayed in the template:

 <p>      :</p> <ul> {% for book in books %} <li>{{ book }}</li> {% endfor %} </ul> 

Then the list will be correct (it will contain all the objects, and not only, for example, the first 100) - because in the context of the template in the books variable, it is the queryset. But in the form it may not be a list of identifiers based on the queryset, but a list of checked checkboxes. In this case, when sending a form from an intermediate page, the queryset will contain only 100 entries, and, accordingly, the action will be performed only with them.

By the way, there is a discussion about this in the comments to this post, as well as a ticket in Trac.

2. Logging to text files with the date and time.

In general, a very simple task, but how to do this in the documentation is not specified. However, there casually refers to the ability to set the formatters dictionary and even gives a small example (albeit without a date and time).

In fact, everything is really simple:

 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'verbose': { 'format': '[%(levelname)s] %(asctime)s %(message)s', 'datefmt': '%Y-%m-%d %H:%M:%S', }, }, 'handlers': { 'mail_admins': { 'level': 'ERROR', 'class': 'django.utils.log.AdminEmailHandler' }, 'books_log_file':{ 'level': 'DEBUG', 'class': 'logging.FileHandler', 'formatter': 'verbose', 'filename': os.path.join(PROJECT_ROOT, 'logs/books.log'), }, }, 'loggers': { 'django.request': { 'handlers': ['mail_admins'], 'level': 'ERROR', 'propagate': True, }, 'books': { 'handlers': ['books_log_file', 'mail_admins'], 'level': 'INFO', 'propagate': True, }, } } 

Here, of course, it is assumed that PROJECT_ROOT is set higher in the settings. For example:

 import os PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__)) 

And if you want to do something else, you can refer to the documentation for Python .

3. Localization of the site if the original text lines are not written in English.

The localization system built into Django, in general, works well, but there is one feature. The fact is that if you translate JS strings , and these strings are not written in English (but, for example, in Russian), then as soon as you create an English translation (django-admin.py makemessages -l en -d djangojs) and compile djangojs.po, this translation will be displayed not only when English is selected, but also when Russian is selected.

That is, you choose Russian, and JS prints lines in English (because it cannot find a Russian translation, and takes English instead - although in this case the translation is not really needed, since the originals of the lines are already in Russian).

The solution (unless, of course, you immediately abandoned the idea of ​​creating a Russian translation of the Russian text) is quite simple here.

You need to add this pattern to urls.py:

 url(r'^jsi18n/null/$', 'django.views.i18n.null_javascript_catalog'), 


And edit the template (usually base.html), adding there:

 {% if request.LANGUAGE_CODE == 'ru' %} <script type="text/javascript" src="{% url django.views.i18n.null_javascript_catalog %}"></script> {% else %} <script type="text/javascript" src="{% url django.views.i18n.javascript_catalog %}"></script> {% endif %} 

It is assumed that urlpattern for django.views.i18n.javascript_catalog is already there, of course.

4. Adding simple pages (flatpages) without specifying sites.

In the current stable version of Django, there is one bug: if you have the flatpages application connected , and by creating such a page, you accidentally forget to select sites from the list, you will get error 500, or, if DEBUG is enabled:

ValueError at / admin / flatpages / flatpage / add /
Can not use none as a query value

Of course, developers already know about this error - moreover, it was fixed three months ago. Actually, in the commit that fixes, changes are made in just one line (plus the test), so you can easily patch Django at your place. He has not yet gotten into stable (including the release of Django 1.4.1, which was a couple of days ago)

In general, use the search, conduct a sufficiently detailed data collection, test. If even some kind of solution is working, keep in mind that there may be nuances everywhere. Pleasant development!

Source: https://habr.com/ru/post/148870/


All Articles