dl Flashcards
card: a serializer is
a class that defines how to convert a record into a dictionary, and define and run validations.
form rest_framework import serializers
class ModelNameSerializer(serializers.ModelSerializer): computed_field = serializers.ReadOnlyField(source="function_name") computed_field_2 = serializers.SerializerMethodField() foreign_objects_field = serializers.CharField(source="foreign_key_field.field_name") foreign_object_serialized = ModelNameSerializer(source='foreign_key_field')
def computed_field_2(self, obj): return obj.name
def validate_field_1(self, value): if value < 1: raise serializers.ValidationError("string") return value
class Meta: model = ModelName fields = ('field_1', 'computed_field', 'foreign_objects_field', 'foreign_object_serialized')
depth=1 to get nested foreign objects (in class Meta) many=True + read_only=True for custom field that returns array of objects (next to source, i.e. field_name_set) source is not needed if you name the custom serializer field the same name as the name in the model
To validate data serialized = ModelNameSerializer(data=data_dictionary) serialized.is_valid() serialized.errors serialized.validated_data serialized.data To do this for an existing instance serialized = ModelNameSerializer(instance_var, data=data_dictionary)
card: a viewset is
a class that defines view functions
from rest_framework.decorators import action
from rest_framework.response import Response
class ModelNameViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): serializer_class = ModelNameSerializer queryset = ModelName.objects.all() # or use permission_classes = (permissions.IsAuthenticatedOrReadOnly,) filter_class = ModelNameFilter def get_queryset(self): user = self.request.user return ModelName.objects.filter(user=user)
# same as @list_route(methods=['get']) queryset gets all @action(methods=["get"], detail=False) #@action marks func for routing. detail=False means dont listen on the detail url /api/model_name/:id/newest/ def newest(self, request): #automatically creates route /newest/ url_param = self.kwargs['param_1'] get_param = request.query_params.get('param_2') instance = self.get_queryset().first() serializer = self.get_serializer_class()(instance) return Response(serializer.data)
# same as @detail_route(methods=['get']) queryset gets one @action(methods=["get"], detail=True) #detail=True means listen on the detail url /api/model_name/:id/newest/ def newest(self, request, pk=None): #pk=None is required for detail=True url_param = self.kwargs['param_1'] get_param = request.query_params.get('param_2') instance = self.get_object() #gets the object of queryset and the id of pk serializer = self.get_serializer_class()(instance) return Response(serializer.data)
card: A router is
an object that generates the url patterns for viewsets you register to it, and gives you an object to throw into urls.py
from rest_framework import routers
from .views import ModelNameViewSet
router = routers.DefaultRouter()
router.register(r’model_name’, ModelNameViewSet, ‘model_url_pattern_name’)
urlpatterns = [
url(r’^api/’, include(router.urls)),
]
card: To turn two lists into the keys and values of a dict, type
To add a value to a dictionary, type
To get a value from a dictionary, type
Else if in python is,
The difference between str.find() and str.index() is
The number of iterations you get from range(10) is
The array you get from range(10) is
The array you get from range(5, 10) is
range(10)[5:] will return,
To add an index to a list for a for loop, type
To loop through the keys and values of a dictionary, type
To spread a dictionary into a function as named arguments, type
To spread a list or tuple into function arguments, type
Since tuples are immutable, you cannot
To create a function that takes one regular argument, then unlimited arguments that get packed into args, and then unlimited named arguments that get packed into kwargs, type
To get the name of the current script file, type
To get the path of the current script file, type
To concatenate two path strings with slashes, type
To remove the last element of a path and effectively refer to the parent, type
This refers to os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
To sort a list, type
To search a file in vim, type
To use pipenv
To turn two lists into the keys and values of a dict
dict(zip(keys_list, values_list))
To add a value to a dictionary, type
my_dict.update({‘key’: ‘value’}) #or
my_dict[‘key’] = ‘value’
Note: These overwrite exists same key
To get a value from a dictionary, type
my_dict[‘key’]
my_dict.get(‘key’)
Else if in python is,
elif
The difference between str.find() and str.index() is
if not found, find() returns -1, index() raises error
The number of iterations you get from range(10) is
10
The array you get from range(10) is
[0, …, 9]
The array you get from range(5, 10) is
[5, …, 9]
range(10)[5:] will return
[5, 6, 7, 8, 9]
To add an index to a list for a for loop, type
for index, item in enumerate(my_list):
To loop through the keys and values of a dictionary, type
for key, value in my_dict.items():
To spread a dictionary into a function as named arguments, type
**dict_name
To spread a list or tuple into a function that accepts *args, type
*list_name
Since tuples are immutable, you cannot
change them inplace, only redefine
To create a function that takes one regular argument, then unlimited arguments that get packed into args, and then unlimited named arguments that get packed into kwargs, type def my_func(param_1, *args, **kwargs): return param_1, args, kwargs new_func('param_1', 'arg_1', 'arg_2', kwarg_1='string', kwarg_2='string') https://www.youtube.com/watch?v=WWm5DxTzLuk
To get the name of the current script file, type
__file__
To get the path of the current script file, type
os.path.abspath(__file__)
To concatenate two path strings with slashes, type
os.path.join(‘string1’, ‘string2’)
To remove the last element of a path and effectively refer to the parent, type
os.path.dirname(path)
This refers to os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
The folder that holds the folder that has the current file in it.
my_list.sort(key=, reverse=) for inplace, sorted(my_list, key=, reverse=) for redefine
To search a file in vim, type
esc ?
and n for next occurrence
To start using pipenv
Start installing using pipenv instead of pip, and it will automatically generate a Pipenv and Pipenv lock file.
To enter the env, type pipenv shell, and exit
https://www.youtube.com/watch?v=zDYL22QNiWk
card:
To rename a git branch
To have add a remote branch to local and then create a branch from it, type
To commit just one file, type
As in the pre push protocol, to merge develop branch into my branch, and then push, type
Doing a git checkout to commit that a branch is pointed at, is not
To push just a branch to remote, type
To clone a branch from github, type
To create a branch and go to it, type
To see who wrote each line of a file and in which commit, type
Git won’t let you merge or pull if you have
Make sure to save all unsaved changes before
Never use
To see the branches on github
To delete a remote branch
To delete a local branch
To delete the last commit, type
Make sure to create a branch
To rename a git branch
git branch -m new_name
To have add a remote branch to local and then create a branch from it, type
git checkout –track new_branch origin/remote_branch
(i think)
To commit just one file, type
git commit -m ‘my notes’ path/to/my/file
e.g. git commit -m “get enrollment once” apps/discussion/views.py (no “a”)
As in the pre push protocol, to merge develop branch into my branch, and then push, type git pull origin develop git checkout new_branch git merge --no-ff develop git push -u origin new_branch
Doing a git checkout to commit that a branch is pointed at, is not
the same as checkout out the branch. Obviously because there can be multiple branches pointed at that commit.
To push one local branch to remote, type
git push -u origin branch_name (-u is –set-upstream)
To see a diff of the modification and the last commit, type
git diff
Or a particular commit
git diff g5f3j1
Git init automatically creates a branch called
master
When you type graph, “HEAD ->” tells you
which branch HEAD is pointed at, basically, what commit you have checked out
To see a graph of commits, type
alias graph=”git log –graph –full-history –all –pretty=format:’%h%x09%d%x20%s %C(dim white)%an’”
git log –graph –abbrev-commit –decorate –format=format:’%C(bold yellow)%h%C(reset)%C(bold yellow)%h%C(reset) %C(bold green)%d%C(reset) %C(white)%s%C(reset) %C(dim white)%an%C(reset)’
git log –all –decorate –oneline –graph
On the graph, in brackets is all the breaches pointed at that commit, both remote and local. Then the commit message.
The asterisk represents the commit to the right of it.
The order of the commits listed is chronological, commits higher than my commit happened after.
When there is no commit in between there will be no line.
Git is really just a history of commits
And if you create a branch, you are just saying ignore commits to a different branch, and mine will have its own history.
The difference between a fast forward merge and recursive merge
Fast forward merges only work if you make a new_branch off of base_branch, add some commits to new_branch, and then when you try to merge to base_branch there were not any new commits after your branch, so the branch pointer just moves to your newest commit and there is no new commit. With recursive, git creates a new merge commit of the latest commit on both branches
https://www.youtube.com/watch?v=AJqup7axNX8
What git branch new_branch_name does is, is
creates a new branch pointer, but that pointer still points to the current commit.
To merge without fast forward, type
git merge –no-ff branch_name
To create a branch off a branch, type
git branch new_branch base_branch
The difference between merging new_branch into base_branch and base_branch into new_branch is
The branch pointer of the branch you are merging from will move to the new merged commit.
A branch is just a
pointer to a commit
Head usually points to
A branch
A branch always points to the latest commit in a branch.
To create a branch off of another branch, type
git checkout -b new_branch base_branch
Do not use git stash, it’s too dangerous.
To remove all uncommitted changes, type
git stash
git stash drop
HEAD is
Basically a pointer to the branch you are looking at, and branch is a pointer to a commit.
A detached HEAD is
When the pointer to the commit you are looking at is not the last commit in the branch
If you see commits that aren’t yours in the github pull request, it’s because those commits are in your branch but not in the base branch.
To clone a branch from github, type
git clone https://github.com/repo.git -b branch_name
To create a branch, type
git branch branch_name
To see who wrote each line of a file and in which commit, type
git blame file_name.py
Git won’t let you merge or pull if you have
uncommitted changes
Make sure to removed all uncommitted changes before pulling or changing branches otherwise guy won’t allow it
git stash, git stash drop
Never use
git add .
To see the branches on github
Use the dropdown on the left
To delete a remote branch
git push –delete remote_name branch_name
To delete a local branch
git branch -d branch_name
To overwrite a local branch to be exactly like remote, type
git reset –hard origin/remote_branch_name
To delete the last commit, type
git reset –hard HEAD^
The branch that you create a branch from matters, determines
https://www.youtube.com/watch?v=FyAAIHHClqI
card: JS
To map to an array with an index, type
To use a for loop that passes in the key and value of object literal, type
To filter through an array, type
To map to an array with an index, type
myArray = myArray.map((item, i) => {}
Note: This doesn’t run in place.
To use a for loop that passes in the key and value of object literal, type
for (const [key, value] of myObj.entries()) {
console.log(key, value);
}
To filter through an array, type
myArray = myArray.filter((item) => false)
Note: This doesn’t run in place.
card: To use fat models, type
Define a custom ModelManager in the model, either redefine .objects or create a custom name
class ModelName(models.Model): objects = ModelNameManager.from_queryset(ModelNameQuerySet)() objects = MyModelManager() #No chainable filters objects = ModelNameQuerySet.as_manager() #skip model manager
Create a model manager, optionally with a default queryset
class ModelNameManager(models.Manager): def get_queryset(self): return super(ModelNameManager, self).get_queryset().filter(field_1 =True) #can add non chainable functions
Create chainable filter functions that return querysets
class ModelNameQuerySet(models.QuerySet): def first(self): return self.filter(field_1=true)
Functions that update a particular
class ModelNameManager(models.Manager): # Optional. this will auto add this filter to all queries that user ModelName.objects.x def get_queryset(self): return super(ModelNameManager, self).get_queryset().filter(field_1 =True) # these methods can be called on ModelName.objects.x but cannot be chained onto a queryset def first(self): return self.filter(field_1=true)
class ModelName(models.Model): objects = ModelNameManager.from_queryset(ModelNameQuerySet)() # to skip the queryset object # objects = MyModelManager() # to skip the models.Manager # objects = ModelNameQuerySet.as_manager() field_1 = models.BooleanField(default=False)
Note:
To set a field to a default models.Manager, type field = models.Manager()
To create a models.Manager on a different field name, type other_field = MyModelManager()
card: To allow get query parameter filters, type
in viewset
filter_backends = (DjangoFilterBackend, )
filter_fields = {‘start_date’: (‘gt’,)}
card: the number associated with every permission is
to make the current user the owner of a file, type
The order of user types is
To see my current username, type
the number associated with every permission is
execute = 1
write = 2
read = 4
to make the current user the owner of a file, type
sudo chown -R $USER file.html
The order of user types is
root, group, everyone
To see my current username, type
whoami
card: select_related and prefetch_related go in
the viewset
card: You put the chainable filtering functions in the
QuerySet of the type of object queryset its going to return.
card: Protocol for bug fixing tasks
Write out the goal of the task myself in my own words so I understand it
Start it the day before, so there’s context in long term memory
Figure out the set up to test that it worked (necessary) usually by finding a student that fits the situation
Use ipdb for figuring out what a request does
Mess around on develop branch
After I understand the implementation, duplicate the project folder for reference and git stash the develop branch
Then create a new branch and the implement cleanly
Use simplenote for implementation ideas
How to debug a celery task?
Import it into the python shell and run it?
card: A generator is
a function that pauses execution when you hit “yield” and is only called by creating an instance and .next() on it.
.next() returns {value: ‘first yield value’, done: false} and then pauses on the next yield.
If you run out of yields you will get {value: undefined, done: true} from calling .next() so instead use a return at the end of function to get {value: ‘return value’, done: true}
The first .next() starts execution. After that, you can pass values into .next(‘string’) and the yield can pass a value into a variable.
function* myGenerator() { let myVar = yield 'first yield value' return 'string3' }
myGeneratorInstance = myGenerator()
myGeneratorInstance.next() // starts execution, returns {value: ‘first yield value’, done: false}
myGeneratorInstance.next(‘string2’) // passes string2 into myVar, returns {value: ‘string3’, done: true}
Card: How sagas basically works is
you create a saga.js
1) create watcher that hijacks dispatched action names
2) create a function that the watcher calls with a let varName = yield call(fetchFunction) in it
3) in the next line, write put({type: ‘ACTION_NAME’, payload: varName})
Note: The fetch function needs to return into the variable before the yield call() to get the data.
You create a watcher function that contains yield takeEvery(‘action_name’, functionToCall)
takeEvery tells saga to intercept every ‘action_name’ and then call functionToCall.
Then in functionToCall you call use put({type: ‘other_action_name’, value: ‘string’})
which will send that object to the reducer
The action name that you dispatch needs to be different than the action name you listen to from the reducer.
The purpose of takeLatest({‘action_name’: functionToCall}) is to debounce. Basically if the function is called again before it finishes, it will only run the newer execution.
Example watcher: function* watchCallApi() { yield takeEvery('CALL_API', getApiData) }
Example dispatcher: function* getApiData(action) { try { const apiReturn = yield call(fetchApiFunction); yield put({type: 'CALL_API_ASYNC', payload: apiReturn}); } catch (e) { yield put({type: FETCH_MENTOR_DATA_FAILURE, error: e.message}); } }
Fetch function: const fetchApiFunction = () => fetch('/url/')...
Card: DL
to fold and unfold all the classes on first level
command k 1, and command k j
short course cohorts always start,
the first Friday of every month
For students, active_course just returns user.profile.active_enrollment.course
Short Courses have a
discussion board, while UXA
A CourseType is
the archetype of a course / course topic, includes UXA phase 1 and UXA phase 2.
CourseType.course_type_category is,
Just a label of the type of course it is, ‘Short Course’
(design 101, branding), ‘Bootcamp’ (UXA phase 1, UXA phase 2), ‘Career Services’, ‘UX Academy Pre-coursework’
A Course is,
A start date, with a fk to a course type. Includes UXA P1, UXA P2.
A Batch is,
Just a record with a start date, and enrollment target, that all the short courses (not bootcamps or Career Services or Pre-coursework), and a countdown timer thats set to the day before the start date at time 18:00:00. The Show_countdown_timer field is only true for the batch record starting soonest in the future, rest are false and the countdown timer date is empty. Short Courses start on the first Friday of every month, so thats when the batch start date should be.
A course has
only one board, and that post has all the posts, just for that course.
UXA cohorts always start,
two Mondays after the first Friday of every month.
BootcampType is,
the archetype/name for bootcamps, (UXA)
Bootcamp is
an instance of Bootcamp archetype with a start date.
I should make my own checklist for github
To know if an enrollment is cancelled, check
enrollment.status = Enrollment.STATUS_ACTIVE, or Enrollment.STATUS_CANCELED
I need to always rewrite the tasks I’m given in asana so I can refactor and make notes and todos. Always copy paste, and rewrite asana tasks.
It might be a good hack when you dont know how to filter something, make a list of IDs and just check if something is in it.
The number of onboard steps there are for short courses and UXA is
4
To run tasks, you must
run both ./runqueue.sh and ./runbeat.sh
I learned:
Do not do unnecessary updates, verify the field is not already the right value.
to figure out a query, find an example object ID to test with in ipdb.
in ipdb, use dir() to see the functions you can call.
It might be a good hack when you dont know how to filter something, make a list of IDs and just check if something is in it. Definitely use qs.values_list(‘id’, flat=True) instead of a list because this its a lazy queryset.
After I have hacked together I solution, I can use git diff, and copy all the changes and save them, so I can git stash andand git stash drop without needing to copy and paste each change one by one.
Dont update a record if its unnecessary.
Dont call .save() from the view.
Use get_object_or_404 when getting an object from url parameter.
To go to the beginning of the line in terminal, ctrl a.
To get a unique set of ids, use set(list(qs.values_list(‘id’, flat=True)))
This script proves that using __enrollments in .filter() does not use the default manager to filter out canceled people.
parent_post = Post.objects.get(id=4019)
StudentUser.objects.filter(enrollment__course__batch=parent_post.board.course.batch).count()
169
inst = StudentUser.objects.filter(enrollment__course__batch=parent_post.board.course.batch).first()
en = Enrollment.objects.filter(user = inst, course__batch = parent_post.board.course.batch).first()
en.status = 1
en.save()
StudentUser.objects.filter(enrollment__course__batch=parent_post.board.course.batch).count()
169
Card: django card
Remember that you can delete on a whole qs. CourseLessonCompletion.objects.filter(enrollment=e).delete()
If I do instance.model_name_set but there are no related instances, what happens? error or none? It returns an empty queryset.
select_related and prefetch_related go
.first() is effectively
The use of @staticmethod is
The main purpose of using def get_context_data(self) is
Sometimes, an alternative to Q objects is
To get all values from a querystring that uses the same key name multiple times, type
?key1=string&key1=string2
If an item is calling .get from a url parameter, use
To redirect using a named url, type
The difference between redirect and HttpResponseRedirect is:
To look up the opposite of a filter (as if using pk__not__in), type
queryset.values() returns
To return the value of an a field thats models.IntegerField(choices=CHOICE_LIST)
To add a virtual column to a queryset that concatenates two existing columns, type
To do a groupby in django, type
To add a virtual column that adds two rows together, type
.annotate(amount_owed=ExpressionWrapper(
F(‘max_owed’) - F(‘total_paid’),
output_field=models.DecimalField(),
)
If you call ModelName.objects.filter(reverse_object_set__field=2), the results can have
Using model_instance.reverse_object_set.all() will use the
To get a unique set of ids, use
When using pk__in in a filter, use
Using .values_list(‘fk_field_name’, flat=True)) vs .values_list(‘user__pk’, flat=True))
Always use pk
I need to use select_related prefetch_related if I will be
select_related and prefetch_related go
before .filter()
.first() is effectively try: queryset[0] except: None
The use of @staticmethod is To create a class function that does not need to be passed self
The main purpose of using def get_context_data(self) is To add key value pairs to it. def get_context_data(self, **kwargs): data = super(ClassName).get_context_data(**kwargs) data['new_key'] = 'value' return data
Sometimes, an alternative to Q objects is
field_name__in=[“option1”, “option2”]
To get all values from a querystring that uses the same key name multiple times, type
?key1=string&key1=string2
request.GET.getlist(‘key1’)
If an item is calling .get from a url parameter, use
from django.shortcuts import get_object_or_404
get_object_or_404(MyModel, pk=1)
In case it doesn’t exist.
To redirect using a named url, type
redirect(‘named_url’)
The difference between redirect and HttpResponseRedirect is:
redirect can accept a model, view or url as the argument and it returns HttpResponseRedirect. HttpResponseRedirect can only accept a url. For DL, use HttpResponseRedirect if the url is a string.
To look up the opposite of a filter (as if using pk__not__in), type
~Q() i.e.
ModelName.objects.filter(~Q(pk__in=[1, 2]))
queryset.values() returns
a list of dictionaries with each record.
To return the value of an a field thats models.IntegerField(choices=CHOICE_LIST)
instance.get_field_name_display()
To add a virtual column to a queryset that concatenates two existing columns, type
ModelName.objects.annotate(new_field=Concat(‘name’, ‘name’, output_field=models.CharField() ))
To do a groupby in django, type
ModelName.objects.values(‘group_by_column’).annotate(agg_field1=Sum(‘id’), agg_field2=Sum(‘id’))
ModelName.objects.all().annotate(amount_owed=ExpressionWrapper(
F(‘column1’) + F(‘column2’),
output_field=models.DecimalField(),
)
If you call ModelName.objects.filter(reverse_object_set__field=2), the results can have
duplicates. In order to get which objects fit the bill, it creates a join table that fills in whichever rows are missing, either right or left, and returns all the objects that were in a row that matched query. use distinct()
Using model_instance.reverse_object_set.all() will use the
default model manager and whatever special custom get_queryset filter you might have added.
To get a unique set of ids, use
set(list(qs.values_list(‘id’, flat=True)))
When using pk__in in a filter, use
pk__in=qs.values_list(‘id’, flat=True) instead of a list because values_list is a lazy queryset.
Using .values_list(‘fk_field_name’, flat=True)) vs .values_list(‘user__pk’, flat=True)) is the same thing
Always use pk
I need to use select_related prefetch_related if I will be
looping over a queryset and using dot notation to access a foreign key objects values
card: To do hack TDD
create a script in base_dir called ts.py
run tests: python manage.py shell_plus < ts.py
Notes: Might want to find a way to make it easy for daniel to run a script of my test cases. Might want to write out my protocol for testing a feature when I am here.
Test Cases
u = User.objects.get(username='Andy') course = u.enrollment_set.all().first().course cu = User.objects.get(username='oceanpebble')
# Canceled = True # Find a student that is canceled, make sure they come up
assert Enrollment.all_enrollments.filter(user=cu, course=course).first().status == Enrollment.STATUS_CANCELED assert cu in course.get_students(include_canceled=True) # Find a student that is active, make sure they come up assert Enrollment.all_enrollments.filter(user=u, course=course).first().status == Enrollment.STATUS_ACTIVE assert u in course.get_students(include_canceled=True)
# Canceled = False # Find a student that is canceled, make sure they dont come up
assert Enrollment.all_enrollments.filter(user=cu, course=course).first().status == Enrollment.STATUS_CANCELED assert cu not in course.get_students(include_canceled=True) # Find a student that is active, make sure they come up assert u.enrollment_set.all().first().status == Enrollment.STATUS_ACTIVE assert u in u.enrollment_set.all().first().course.get_students(include_canceled=False)
# Sanity checks assert ...
Card: To create a custom admin sidebar filter for the list view
create a class that subclasses admin.SimpleListFilter, then add that class to list_filters = [] in your custom ModelAdmin
class ModelNameListFilter(admin.SimpleListFilter): title = "string" # Just the display name on the side parameter_name = "string" # the key in the get params that will tell this filter to activate in the chain of filters.
# Defines the list of the choice options to show on the side, and the value that will be put into the get params. Must be a list of tuples. def lookups(self, request, model_admin): return [ ('internal_value', 'Visible Option'), ('internal_value', 'Visible Option'), ]
# Define whatever qs filters you want def queryset(self, request, model_admin): filter_value = self.value() # returns the value passed into the get parameter defined in parameter_name # if you have the same parameter multiple times, to aggregate the values into a list under the param name, use filter_values = request.GET.getlist(self.parameter_name)
qs_filters = {} qs_filters['field_name'] = self.value() return return queryset.filter(**qs_filters)
# Add it to your custom admin class class ModelNameAdmin(admin.ModelAdmin): list_filter = (ModelNameFilter,)
https://www.youtube.com/watch?v=_-J7fra7Ub8
To create a parent class, then inherit from a parent class and overwrite some values, type
use @class_method
use super
A subclass is a class that inherits all the properties and methods from a parent class and overwrites or adds some.
class ParentClassName(Object): # class variables are called on the class name, not the instance, go above the init function. If you change it's value, all instances will change their value immediately. class_variable = 10
def \_\_init\_\_(self, *args, **kwargs): # access args with args[0], and krwargs with kwargs['key'] self.my_attribute = args[0] self.my_attribute2 = kwargs['key']
def get_value(self, param): return ParentClassName.class_variable
# A class method is called on the class name. I passes the class name as a param, so you can alter the class in the function, although you could just write ClassName in the function, better to manipulate class attributes (no self.) with class methods. @classmethod def get_value2(cls, param): return cls.class_variable
# Another use case for class method is alternative constructor. You'd use this like # instance = ParentClassName.from_string(key='value') @classmethod def from_string(cls, *args, **kwarg): var_name = kwargs.get('key') return cls(param_1, var_name)
The purpose of super(CurrentClass, self).parent_class_function() is to access the parent function and call something thats defined there. Useful is name is overwritten in the current function. Passing in the current class is required in python2.
The value of using getters and setters is, if you suddenly need to add logic to what used to be a variable, if you create getter and setter using @property then it will behave the same in the rest of the codebase, but the underlying mechanism would change.
To set up django import export
installed_app += ‘import_export’
create a resource, class the defines how your data will be exported
class ModelNameResource(resources.ModelResource): custom_field = Field()
class Meta: model = ModelName fields = ('custom_field', 'foreign_key_field\_\_field_name',) # dunders will work, the column name will be foreign_key_field\_\_field_name and it will be ignored when uploading.
def dehydrate_custom_field(self, obj): return obj.field_name # obj represents one record of this model
Prefetch() is
and object you can call inside .prefeth_related() that allows you to change the starting queryset before the join happens.
So if I wanted to have the related objects sorted when I go to them, I could type
ModelName.objects.prefetch_related(Prefetch(‘model_name_set’, queryset=ReverseModelName.objects.order_by(‘-created_at’)))
Or if I wanted to have some of the related records filtered out
ModelName.objects.prefetch_related(Prefetch(‘model_name_set’, queryset=ReverseModelName.objects.filter(price__gt=10)))
https://stackoverflow.com/questions/48071397/django-prefetch-relateds-prefetch-order-by
@cached_property
is decorator you can put on model methods to make them run once when an instance of that model is created, and then the result will be a property cached, instead of actually calling the function.
querysets only hit the database if they are
evaluated, basically, if you do anything from this list to to them.
check an attribute or
slice[], len(), list(), bool() or use as conditional value
to do a reverse lookup ( a reverse foreign key) the class name.
has no underscores.
Class ParentModel(models.Model) child = models.ForeignKey('Child')
child_instance.parentmodel_set
to restore from new db snapshot, type command
fab db.restore
How redux works with sagas is basically
The reducer has set an initial state.
In the component, you use mapDispatchToProp to be able to call actions from the component.
When you call that action, a sagas watcher catches it, and then calls a worker function. That function does something (i.e. fetch) and then dispatches a different action with the payload. That action triggers a case in the reducer, and the reducer pushes that data to the state. Then you use mapStateToProps to access that prop in the component.
Pretty much, every state property needs its own reducer and reducer file. You can see the rootreducer as the apps full state.
dont forget to register your watchers
sagaMiddleware.run(fetchTimezonesSaga);