Kindle Notes & Highlights
Read between
March 20 - March 27, 2021
uuid
path
For example, the ^year/(\d+)/ pattern will send the value 1980 as the second argument (the first being the request) to the view. The problem with positional arguments is that it is very easy to mix up the order. Hence, we have name-based arguments where each captured value can be named. Our example will now look like ^year/(?P<year>\d+)/. This means that the view will be called with a keyword argument year being equal to 1980.
If you have a class-based view, you can access your positional arguments in self.args and name-based arguments in self.kwargs
Always name your patterns. It helps in decoupling your code from the exact URL paths. For instance, in the previous URLConf, if you want to redirect to the About page, it might be tempting to use redirect("/about"). Instead, use redirect("about"), as it uses the name rather than the path. Here are some more examples of reverse lookups: >>> from django.urls import reverse >>> reverse("hello_fn") /hello-fn/ >>> reverse("year_view", kwargs={"year":"793"}) /year/793/ Names must be unique. If two patterns have the same name, they will not work.
Pattern names used in a namespace only have to be unique within that namespace and not the entire project. It is recommended that you give every app its own namespace. For example, we can create a viewschapter namespace with only the URLs of this chapter by including this line in the root URLconf: path('', include(viewschapter.urls, namespace='viewschapter')), Now we can use pattern names, such as feed or anything else as long as they are unique within that app namespace. While referring to a name within a namespace, you will need to mention the namespace, followed by a : before the name. It
...more
A good rule of thumb is to keep all the special cases at the top. Broader or more general patterns can be mentioned further down. The broadest, a catch-all-if present, can go at the very end.
One of the key insights is that a URI is an identifier to a resource. A resource can be anything, such as an article, a user, or a collection of resources, such as events. Generally speaking, resources are nouns. The web provides you with some fundamental HTTP verbs to manipulate resources: GET, POST, PUT, PATCH, and DELETE. These are not part of the URL itself. Hence, it is bad practice to use a verb in the URL to manipulate a resource. For example, the following example URL is considered bad: http://site.com/articles/submit/ Instead, you should remove the verb and use the POST action to this
...more
Django Template Language
>>> "Dr. Oct has {0} arms and says: {1}".format(DrOct().arms, DrOct().speak()) 'Dr. Oct has 4 arms and says: You have a train to catch.' >>> mydict["key"] 'value' >>> mylist[1] 20 In Django's template equivalent, it is as follows: Dr. Oct has {{ s.arms }} arms and says: {{ s.speak }} {{ mydict.key }} {{ mylist.1 }} Notice how speak, a method that takes no arguments except self, is treated like an attribute here.
var.method1().method2(arg), Django uses the pipe syntax {{ var|method1|method2:"arg" }}, which is similar to Unix filters. However, this syntax only works for built-in or custom-defined filters. Another limitation is that filters cannot access the template context. They only work with the data passed into them and their arguments.
>>> title="SuperBook" >>> title.upper()[:5] 'SUPER' The following is its Django template equivalent: {{ title|upper|slice:':5' }}"
the template system does not intentionally allow the following: Assignment to variables Function call arguments Advanced logic This decision was made to prevent you from adding business logic in templates. From my experience with PHP or ASP-like languages, mixing logic with presentation can be a maintenance nightmare.
in DTL the method call is implied as in the following example: {% for post in user.public_posts %} ... {% endfor %} But in Jinja2, we invoke the public_posts method similar to a Python function call: {% for post in user.public_posts() %} ... {% endfor %}
The default project layout created by the startproject command does not define a location for your templates. This is very easy to configure. Create a directory named templates in your project's root directory. Specify the value for DIRS inside the TEMPLATES variable in your settings.py: (can be found within superbook/settings/base.py in our superbook project) BASE_DIR = os.path.dirname(os.path.dirname(__file__)) TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], 'APP_DIRS': True,
...more
Your templates can also reside within your apps (if APP_DIRS is true).
Keep all app-specific templates inside the app's template directory within a separate directory, for example projroot/app/templates/app/template.html— notice how app appears twice in the path
Finally, the render method of a Template object receives the context and renders the output. This might be an HTML, XML, email, CSS, or any textual output.
Now you can include the Bootstrap assets in your templates, as follows: {% load staticfiles %} <head> <link href="{% static 'css/bootstrap.min.css' %}"
Last but least and least, you can make your CSS classes more meaningful by replacing structural class names, such as row or col-lg-9, with semantic tags, such as main or article. You can do this with a few lines of SASS code to @extend the Bootstrap classes, as follows: @import "bootstrap"; body > main { @extend .row; article { @extend .col-lg-9; } } This is possible due to a feature called mixins
Usually, all inheritance chains can be traced back to a common root, base.html; hence, the pattern's name: Template inheritance tree
You can create a context processor, which will add a context variable that can be used in all your templates globally. But this is not advisable for common markup such as sidebars as it violates the separation of concerns by moving presentation out of the template layer.
Try to display the object's unique information in its str representation (or Unicode representation, in the case of Python 2.x code),
get_absolute_url(): This method is handy if you like to switch between the admin site and the object's corresponding detail view on your (nonadmin) website. If this method is defined, then a button labeled View on site
ordering: Without this Meta option, your entries can appear in any order as returned from the database.
verbose_name_plural
However, you can use many more features of the admin by creating a custom ModelAdmin class. In this case, we customize it as follows: # admin.py class SightingAdmin(admin.ModelAdmin): list_display = ('superhero', 'power', 'location', 'sighted_on') date_hierarchy = 'sighted_on' search_fields = ['superhero'] ordering = ['superhero']
ordering: This option takes precedence over your model's default ordering. It is useful if you prefer a different ordering in your admin screen,
Essentially, rectifying most misuses of the admin interface involve creating more powerful tools for certain sets of users. However, don't take the easy (and wrong) path of granting them admin access.
You will need to copy base_site.html from the admin templates to admin/base_site.html in one of your template's directories. Then, add the following lines to the end: {% block extrastyle %} <link href='http://fonts.googleapis.com/css?family=Special+Elite' rel='stylesheet' type='text/css'> <style type="text/css"> body, td, th, input { font-family: 'Special Elite', cursive; } </style> {% endblock %}
one of the only telltale signs that someone is running Django is that when you navigate to http://example.com/admin/, you will be greeted by the blue login screen. In production, it is recommended that you change this location to something less obvious.
new features that have a significant impact in terms of usability or performance ought to be rolled out in a phased manner. In other words, deployment should be decoupled from a release. Simplistic release processes activate new features as soon as they are deployed. This can potentially have catastrophic results,
in large sites, it is important to decouple deployment of new features in production and their activation. Even if they are activated, they are sometimes only seen by a select group of users.
Several Django packages provide feature flags, such as gargoyle and django-waffle.
Trials: A feature flag can also be conditionally active for certain users. These can be your own staff or certain early adopters that you may be targeting, as follows: def my_view(request): if flag_is_active(request, 'flag_name'): # Behavior if flag is active.
A/B testing: This is quite similar to trials, except that users are selected randomly within a controlled experiment. This method is quite common in web design and is used to identify which changes can increase the conversion rates. The following is how such a view can be written: def my_view(request): if sample_is_active(request, 'new_design'): # Behavior for test sample.
Performance testing: Sometimes, it is hard to measure the impact of a feature on server performance.
Limit externalities: We can also use feature flags as a site-wide feature switch that reflects the availability of its services.
is_bound: If this returns false, then it is an unbound form, that is, a fresh form with empty or default field values.
is_valid(): If this returns true, then every field in the bound form has valid data.
from django import forms class PersonDetailsForm(forms.Form): name = forms.CharField(max_length=100) age = forms.IntegerField() This class can be initiated in a bound or unbound manner, as shown in the following code: >>> f = PersonDetailsForm() >>> print(f.as_p()) <p><label for="id_name">Name:</label> <input type="text" name="name" maxlength="100" required id="id_name" /></p> <p><label for="id_age">Age:</label> <input type="number" name="age" required id="id_age" /></p> >>> f.is_bound False >>> g = PersonDetailsForm({"name": "Blitz", "age": "30"}) >>> print(g.as_p()) <p><label
...more
Never trust the user input.
Forms try to abstract away the fact that strings are passed around and give you clean Python objects that you can use. Always use the cleaned_data from your form rather than raw data from the user.
The django-crispy-forms package makes the form template code more crisp (that is, concise). It moves all the presentation and layout into the Django form itself. This way, you can write more Python code and less HTML.
class ClassBasedFormView(generic.View): template_name = 'form.html' def get(self, request): form = PersonDetailsForm() return render(request, self.template_name, {'form': form}) def post(self, request): form = PersonDetailsForm(request.POST) if form.is_valid(): # Success! We can use form.cleaned_data now return redirect('success') else: # Invalid form! Reshow the form with error highlighted return render(request, self.template_name, {'form': form})
from django.urls import reverse_lazy class GenericFormView(generic.FormView): template_name = 'form.html' form_class = PersonDetailsForm success_url = reverse_lazy("success") We need to use reverse_lazy in this case because the URL patterns are not loaded when the View file is imported.