dl Flashcards

1
Q

card: a serializer is

A

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)
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

card: a viewset is

A

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)
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

card: A router is

A

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)),
]

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

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

A

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

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

A

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

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

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

card: To use fat models, type

A

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()

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

card: To allow get query parameter filters, type

A

in viewset
filter_backends = (DjangoFilterBackend, )
filter_fields = {‘start_date’: (‘gt’,)}

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

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

A

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

card: select_related and prefetch_related go in

A

the viewset

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

card: You put the chainable filtering functions in the

A

QuerySet of the type of object queryset its going to return.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

card: Protocol for bug fixing tasks

A

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?

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

card: A generator is

A

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}

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Card: How sagas basically works is

A

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/')...
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Card: DL

A

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

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

A

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

17
Q

card: To do hack TDD

A

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 ...
18
Q

Card: To create a custom admin sidebar filter for the list view

A

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

19
Q

To create a parent class, then inherit from a parent class and overwrite some values, type

A

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.

20
Q

To set up django import export

A

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
21
Q

Prefetch() is

A

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

22
Q

@cached_property

A

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.

23
Q

querysets only hit the database if they are

A

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

24
Q

to do a reverse lookup ( a reverse foreign key) the class name.

A

has no underscores.

Class ParentModel(models.Model)
    child = models.ForeignKey('Child')

child_instance.parentmodel_set

25
Q

to restore from new db snapshot, type command

A

fab db.restore

26
Q

How redux works with sagas is basically

A

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);