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