2121 + [ Commit message] ( #commit-message )
2222* [ Python] ( #python )
2323 + [ For code in general] ( #for-code-in-general )
24- - [ PEP8] ( #pep8 )
25- - [ String quotation marks] ( #string-quotation-marks )
2624 - [ Quotation marks inside strings] ( #quotation-marks-inside-strings )
2725 - [ String concatenation] ( #string-concatenation )
28- - [ Trailing commas] ( #trailing-commas )
29- - [ Operator wrapping] ( #operator-wrapping )
3026 - [ Imports] ( #imports )
3127 + [ For each module (file)] ( #for-each-module-file )
32- - [ Empty/blank lines] ( #emptyblank-lines )
3328 - [ Folder/directory location] ( #folderdirectory-location )
3429 - [ Filename] ( #filename )
3530 + [ Migration filename] ( #migration-filename )
5550 + [ Model field argument value] ( #model-field-argument-value )
5651* [ Django templates / HTML / CSS] ( #django-templates--html--css )
5752 + [ For code in general] ( #for-code-in-general-1 )
58- - [ String quotation marks] ( #string-quotation-marks-1 )
53+ - [ String quotation marks] ( #string-quotation-marks )
5954 - [ Hex (color) code literals] ( #hex-color-code-literals )
6055 + [ For each file] ( #for-each-file )
61- - [ Empty/blank lines] ( #emptyblank-lines-1 )
56+ - [ Empty/blank lines] ( #emptyblank-lines )
6257 - [ Filename] ( #filename-1 )
6358 + [ Django template filenames] ( #django-template-filenames )
6459 + [ CSS filenames] ( #css-filenames )
7873 - [ Stylesheet rule order] ( #stylesheet-rule-order )
7974* [ JavaScript] ( #javascript )
8075 + [ For code in general] ( #for-code-in-general-2 )
81- - [ String quotation marks] ( #string-quotation-marks-2 )
76+ - [ String quotation marks] ( #string-quotation-marks-1 )
8277 + [ For each file] ( #for-each-file-1 )
8378 - [ Filename] ( #filename-2 )
8479 + [ For each function] ( #for-each-function )
@@ -152,37 +147,6 @@ with reasoning, examples and tips:
152147
153148### For code in general
154149
155- #### PEP8
156-
157- In general, we follow the [ PEP 8] ( https://www.python.org/dev/peps/pep-0008/ ) style guide.
158- <br />* Tip: PyCharm marks (most) PEP 8 violations with a yellow squiggly line.
159- Additionally, PyCharm can easily fix most of these inconsistencies - and enforce various other parts of this style guide -
160- using the [ Reformat Code feature] ( https://www.jetbrains.com/pycharm/guide/tips/reformat-code/ ) (<kbd >Ctrl+Alt+L</kbd >/<kbd >⌥⌘L</kbd > by default) -
161- possibly requiring some tweaking of the settings.*
162-
163- #### String quotation marks
164-
165- Use ` ' ` for "code values" that are meant to be compared exactly against some other values.
166- ** In short: if these strings are changed, things * might* break.**
167- Examples include:
168- * Existing paths, like file paths for templates, or dotted module paths.
169- * Names of variables or attributes, like object attributes, keyword arguments, or template context variables.
170-
171- Use ` " ` for messages, names, etc. that are not supposed to be compared to existing values.
172- ** In short: if these strings are changed, nothing * should* break.**
173- Examples include:
174- * Text in a natural language, like messages that are shown to users or developers.
175- * Path definitions - e.g. the first argument passed to the [ ` path() ` function] ( https://docs.djangoproject.com/en/stable/ref/urls/#path ) -
176- as these are not supposed to be directly referenced elsewhere
177- (they should instead be inserted using the ` reverse() ` function or the ` url ` template tag)
178- and can in principle be changed freely without altering the functionality in any way.
179- * Docstrings.
180-
181- If unsure, or if the case in question is in a grey area, use ` ' ` .
182-
183- * [ This specific coding style is loosely based on
184- this library's coding standards] ( https://docs.ckan.org/en/ckan-2.7.3/contributing/python.html#use-single-quotes ) .*
185-
186150#### Quotation marks inside strings
187151
188152Prefer using the proper Unicode characters for quotation marks in the language of the string in question
@@ -199,41 +163,6 @@ if an f-string is hard to read, extract inserted code to variables, and insert t
199163For translation strings (using ` gettext ` or ` gettext_lazy ` ), use the standard ` format() ` method for concatenation.
200164For example:<br />` _("{chant} Batman!").format(chant="NaN" * 15) ` (where ` gettext_lazy ` is imported as ` _ ` ).
201165
202- #### Trailing commas
203-
204- Always leave a trailing comma after the last element in a wrapped list/tuple/set/dictionary initialization expression
205- or wrapped function/constructor call.
206-
207- #### Operator wrapping
208-
209- When wrapping an expression containing operators (like ` + ` , ` & ` and ` and ` ),
210- place the operators first on each wrapped line (instead of last on the previous lines).
211- This also applies to similar things, like list comprehension expressions and conditional expressions (aka ternary operator).
212-
213- To illustrate, a good example of wrapping the following code:
214- ``` python
215- def func (long_condition_expr , other_long_expr , list_of_lists ):
216- if long_condition_expr and long_condition_expr:
217- return other_long_expr + other_long_expr
218- return [element for inner_list in list_of_lists for element in inner_list if element is not None ]
219- ```
220- can be:
221- ``` python
222- def func (long_condition_expr , other_long_expr , list_of_lists ):
223- if (long_condition_expr
224- and long_condition_expr):
225- return (
226- other_long_expr
227- + other_long_expr
228- )
229- return [
230- element
231- for inner_list in list_of_lists
232- for element in inner_list
233- if element is not None
234- ]
235- ```
236-
237166#### Imports
238167
239168Group imports in three "paragraphs" (separated by an empty line) in the following order:
@@ -253,10 +182,6 @@ All imports in a file that are from the same app as the mentioned file, should b
253182
254183### For each module (file)
255184
256- #### Empty/blank lines
257-
258- Leave two empty lines between class and function (i.e. not method) definitions, and after all the imports in a module.
259-
260185#### Folder/directory location
261186
262187* Tests should always be placed within a ` tests ` directory per app.
@@ -470,12 +395,16 @@ from django.urls import path
470395
471396
472397urlpatterns = [
473- path(" events/" , ... , name = ' event_list' ),
474- path(" events/add/" , ... , name = ' event_create' ),
475- path(" events/<int:pk>/" , ... , name = ' event_detail' ),
476- path(" events/<int:pk>/change/" , ... , name = ' event_update' ),
477- path(" events/<int:pk>/occurrences/" , ... , name = ' event_occurrence_list' ),
478- path(" events/<int:pk>/occurrences/<int:occurrence_pk>/" , ... , name = ' event_occurrence_detail' ),
398+ path(" events/" , ... , name = " event_list" ),
399+ path(" events/add/" , ... , name = " event_create" ),
400+ path(" events/<int:pk>/" , ... , name = " event_detail" ),
401+ path(" events/<int:pk>/change/" , ... , name = " event_update" ),
402+ path(" events/<int:pk>/occurrences/" , ... , name = " event_occurrence_list" ),
403+ path(
404+ " events/<int:pk>/occurrences/<int:occurrence_pk>/" ,
405+ ... ,
406+ name = " event_occurrence_detail" ,
407+ ),
479408]
480409```
481410would be:
@@ -484,17 +413,17 @@ from django.urls import include, path
484413
485414
486415event_occurrence_urlpatterns = [
487- path(" " , ... , name = ' event_occurrence_list' ),
488- path(" <int:pk>/" , ... , name = ' event_occurrence_detail' ),
416+ path(" " , ... , name = " event_occurrence_list" ),
417+ path(" <int:pk>/" , ... , name = " event_occurrence_detail" ),
489418]
490419specific_event_urlpatterns = [
491- path(" " , ... , name = ' event_detail' ),
492- path(" change/" , ... , name = ' event_update' ),
420+ path(" " , ... , name = " event_detail" ),
421+ path(" change/" , ... , name = " event_update" ),
493422 path(" occurrences/" , include(event_occurrence_urlpatterns)),
494423]
495424event_urlpatterns = [
496- path(" " , ... , name = ' event_list' ),
497- path(" add/" , ... , name = ' event_create' ),
425+ path(" " , ... , name = " event_list" ),
426+ path(" add/" , ... , name = " event_create" ),
498427 path(" <int:pk>/" , include(specific_event_urlpatterns)),
499428]
500429
@@ -545,7 +474,7 @@ urlpatterns = [
545474 path(" admin/" , include(admin_urlpatterns)),
546475 path(" api/" , include(api_urlpatterns)),
547476 # The `news` app's base path route argument ("news/")
548- path(" news/" , include(' news.urls' )),
477+ path(" news/" , include(" news.urls" )),
549478]
550479```
551480
@@ -558,7 +487,7 @@ Use `snake_case`.
558487
559488An exception to this is when the variable value is a reference to a specific model class -
560489in which case, the variable should have the same name as the model it references;
561- for example: ` InheritanceGroup = apps.get_model(' groups', ' InheritanceGroup' ) ` .
490+ for example: ` InheritanceGroup = apps.get_model(" groups", " InheritanceGroup" ) ` .
562491
563492#### Model field definition arguments
564493
@@ -601,7 +530,7 @@ Sort the keyword arguments in the following order:
601530
602531Use ` " ` for everything pure HTML and CSS.
603532
604- Inside template tags and filters, use [ the same quotation marks as for Python] ( #string-quotation-marks ) .
533+ Inside template tags and filters, use the same quotation marks as for Python.
605534Examples include:
606535* ` ' ` for:
607536 * ` url ` names
@@ -931,15 +860,15 @@ class EventOccurrence(models.Model):
931860 event = models.ForeignKey(
932861 to = Event,
933862 on_delete = models.CASCADE ,
934- related_name = ' occurrences' ,
863+ related_name = " occurrences" ,
935864 )
936865
937866
938867def get_context_data ():
939868 # Prefetching related objects to avoid unnecessary additional database lookups
940869 return {
941- ' occurrence_objects' : EventOccurrence.objects.select_related(' event' ),
942- ' event_objects' : Event.objects.prefetch_related(' occurrences' ),
870+ " occurrence_objects" : EventOccurrence.objects.select_related(" event" ),
871+ " event_objects" : Event.objects.prefetch_related(" occurrences" ),
943872 }
944873```
945874``` html
@@ -978,15 +907,15 @@ The number of database queries a request triggers, can be measured by adding the
978907from web.settings import LOGGING
979908
980909
981- LOGGING [' loggers' ][ ' django.db.backends' ] = {
982- ' level' : ' DEBUG' ,
983- ' handlers' : [' console' ],
910+ LOGGING [" loggers" ][ " django.db.backends" ] = {
911+ " level" : " DEBUG" ,
912+ " handlers" : [" console" ],
984913}
985- """ This would require a logging handler named `console`, which would look something like this:
986- ' console' : {
987- ' level': ' DEBUG' ,
988- ' filters' : [...],
989- ' class': ' logging.StreamHandler' ,
914+ """ This would require a logging handler named `console`, which could look like this:
915+ " console" : {
916+ " level": " DEBUG" ,
917+ " filters" : [...],
918+ " class": " logging.StreamHandler" ,
990919}
991920"""
992921```
@@ -1153,18 +1082,20 @@ class EventOccurrenceForm(forms.Form):
11531082 def clean (self ):
11541083 cleaned_data = super ().clean()
11551084 # The fields won't exist in the cleaned data if they were submitted empty (even if they're both (by default) required)
1156- start_time = cleaned_data.get(' start_time' )
1157- end_time = cleaned_data.get(' end_time' )
1085+ start_time = cleaned_data.get(" start_time" )
1086+ end_time = cleaned_data.get(" end_time" )
11581087
11591088 # These might be `None`
11601089 if start_time and end_time:
11611090 if start_time > end_time:
11621091 error_message = _(" The event cannot end before it starts." )
1163- code = ' invalid_relative_to_other_field'
1164- raise forms.ValidationError({
1165- ' start_time' : forms.ValidationError(error_message, code = code),
1166- ' end_time' : forms.ValidationError(error_message, code = code),
1167- })
1092+ code = " invalid_relative_to_other_field"
1093+ raise forms.ValidationError(
1094+ {
1095+ " start_time" : forms.ValidationError(error_message, code = code),
1096+ " end_time" : forms.ValidationError(error_message, code = code),
1097+ }
1098+ )
11681099
11691100 return cleaned_data
11701101```
0 commit comments