Skip to content

Commit

Permalink
Merge pull request #15 from hfidelis/dev
Browse files Browse the repository at this point in the history
dev>main
  • Loading branch information
hfidelis authored Aug 29, 2024
2 parents f2fe085 + 27cbb0a commit 0dfbb5f
Show file tree
Hide file tree
Showing 11 changed files with 374 additions and 57 deletions.
Binary file added src/assets/images/me-irl.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions src/components/icons/IconFacebook.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<script lang="ts" setup>
const props = defineProps({
color: {
type: String,
required: false,
default: '#0b0b0b',
},
size: {
type: [String, Number],
required: false,
default: '32',
},
})
</script>

<template>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
:width="`${props.size}px`"
:heigth="`${props.size}px`"
>
<path
d="M12 2.04C6.5 2.04 2 6.53 2 12.06C2 17.06 5.66 21.21 10.44 21.96V14.96H7.9V12.06H10.44V9.85C10.44 7.34 11.93 5.96 14.22 5.96C15.31 5.96 16.45 6.15 16.45 6.15V8.62H15.19C13.95 8.62 13.56 9.39 13.56 10.18V12.06H16.34L15.89 14.96H13.56V21.96A10 10 0 0 0 22 12.06C22 6.53 17.5 2.04 12 2.04Z"
:fill="props.color"
/>
</svg>
</template>
28 changes: 28 additions & 0 deletions src/components/icons/IconTwitter.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<script lang="ts" setup>
const props = defineProps({
color: {
type: String,
required: false,
default: '#0b0b0b',
},
size: {
type: [String, Number],
required: false,
default: '32',
},
})
</script>

<template>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
:width="`${props.size}px`"
:heigth="`${props.size}px`"
>
<path
d="M22.46,6C21.69,6.35 20.86,6.58 20,6.69C20.88,6.16 21.56,5.32 21.88,4.31C21.05,4.81 20.13,5.16 19.16,5.36C18.37,4.5 17.26,4 16,4C13.65,4 11.73,5.92 11.73,8.29C11.73,8.63 11.77,8.96 11.84,9.27C8.28,9.09 5.11,7.38 3,4.79C2.63,5.42 2.42,6.16 2.42,6.94C2.42,8.43 3.17,9.75 4.33,10.5C3.62,10.5 2.96,10.3 2.38,10C2.38,10 2.38,10 2.38,10.03C2.38,12.11 3.86,13.85 5.82,14.24C5.46,14.34 5.08,14.39 4.69,14.39C4.42,14.39 4.15,14.36 3.89,14.31C4.43,16 6,17.26 7.89,17.29C6.43,18.45 4.58,19.13 2.56,19.13C2.22,19.13 1.88,19.11 1.54,19.07C3.44,20.29 5.7,21 8.12,21C16,21 20.33,14.46 20.33,8.79C20.33,8.6 20.33,8.42 20.32,8.23C21.16,7.63 21.88,6.87 22.46,6Z"
:fill="props.color"
/>
</svg>
</template>
28 changes: 28 additions & 0 deletions src/components/icons/IconWhatsapp.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<script lang="ts" setup>
const props = defineProps({
color: {
type: String,
required: false,
default: '#0b0b0b',
},
size: {
type: [String, Number],
required: false,
default: '32',
},
})
</script>

<template>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
:width="`${props.size}px`"
:heigth="`${props.size}px`"
>
<path
d="M12.04 2C6.58 2 2.13 6.45 2.13 11.91C2.13 13.66 2.59 15.36 3.45 16.86L2.05 22L7.3 20.62C8.75 21.41 10.38 21.83 12.04 21.83C17.5 21.83 21.95 17.38 21.95 11.92C21.95 9.27 20.92 6.78 19.05 4.91C17.18 3.03 14.69 2 12.04 2M12.05 3.67C14.25 3.67 16.31 4.53 17.87 6.09C19.42 7.65 20.28 9.72 20.28 11.92C20.28 16.46 16.58 20.15 12.04 20.15C10.56 20.15 9.11 19.76 7.85 19L7.55 18.83L4.43 19.65L5.26 16.61L5.06 16.29C4.24 15 3.8 13.47 3.8 11.91C3.81 7.37 7.5 3.67 12.05 3.67M8.53 7.33C8.37 7.33 8.1 7.39 7.87 7.64C7.65 7.89 7 8.5 7 9.71C7 10.93 7.89 12.1 8 12.27C8.14 12.44 9.76 14.94 12.25 16C12.84 16.27 13.3 16.42 13.66 16.53C14.25 16.72 14.79 16.69 15.22 16.63C15.7 16.56 16.68 16.03 16.89 15.45C17.1 14.87 17.1 14.38 17.04 14.27C16.97 14.17 16.81 14.11 16.56 14C16.31 13.86 15.09 13.26 14.87 13.18C14.64 13.1 14.5 13.06 14.31 13.3C14.15 13.55 13.67 14.11 13.53 14.27C13.38 14.44 13.24 14.46 13 14.34C12.74 14.21 11.94 13.95 11 13.11C10.26 12.45 9.77 11.64 9.62 11.39C9.5 11.15 9.61 11 9.73 10.89C9.84 10.78 10 10.6 10.1 10.45C10.23 10.31 10.27 10.2 10.35 10.04C10.43 9.87 10.39 9.73 10.33 9.61C10.27 9.5 9.77 8.26 9.56 7.77C9.36 7.29 9.16 7.35 9 7.34C8.86 7.34 8.7 7.33 8.53 7.33Z"
:fill="props.color"
/>
</svg>
</template>
95 changes: 95 additions & 0 deletions src/components/social-share/SocialShare.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<script setup lang="ts">
import { ref, watch } from 'vue'
import IconFacebook from '@/components/icons/IconFacebook.vue'
import IconTwitter from '@/components/icons/IconTwitter.vue'
import IconLinkedin from '@/components/icons/IconLinkedin.vue'
import IconWhatsapp from '@/components/icons/IconWhatsapp.vue'
import SocialOption from '@/types/components/social-share/SocialOption.type'
interface SocialShareProps {
type: SocialOption
url: string
isDark: boolean
}
const props = defineProps<SocialShareProps>()
const currentColor = ref<string>('white')
const getContextIcon = (type: SocialOption) => {
const COMPONENTS: { [key in SocialOption]: any } = {
facebook: IconFacebook,
twitter: IconTwitter,
linkedin: IconLinkedin,
whatsapp: IconWhatsapp,
}
return COMPONENTS[type]
}
const getContextColor = (type: SocialOption) => {
const COLORS: { [key in SocialOption]: string } = {
facebook: '#1877f2',
twitter: '#1da1f2',
linkedin: '#0077b5',
whatsapp: '#25d366',
}
return COLORS[type]
}
watch(
() => props.type,
() => {
currentColor.value = getContextColor(props.type)
},
{ immediate: true }
)
</script>

<template>
<div>
<a
:href="props.url"
target="_blank"
rel="noopener noreferrer"
class="share__button"
:class="isDark ? 'dark' : 'light'"
:style="{ backgroundColor: getContextColor(props.type) }"
>
<component
:is="getContextIcon(props.type)"
:size="20"
:color="'white'"
/>
</a>
</div>
</template>

<style lang="scss" scoped>
@import '@/styles/app.scss';
.share__button {
display: inline-flex;
justify-content: center;
align-items: center;
border-radius: 50%;
padding: 0.3rem;
transition: all 0.3s ease-in-out;
&:hover {
transform: scale(1.1);
filter: brightness(1.8);
}
&.dark {
box-shadow: $dark-mode-shadow;
}
&.light {
box-shadow: $light-mode-shadow;
}
}
</style>
4 changes: 3 additions & 1 deletion src/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@
"title": "Oops! It looks like this post doesn't exists...",
"subtitle": "Maybe you typed the wrong address or the post has been removed.",
"back": "Back to home"
}
},
"share": "Share",
"defaultAuthor": "Heitor Fidelis"
}
}
}
4 changes: 3 additions & 1 deletion src/locales/pt-BR.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@
"title": "Ops! Parece que este post não existe...",
"subtitle": "Talvez você tenha digitado o endereço errado ou o post foi removido.",
"back": "Voltar para o início"
}
},
"share": "Compartilhar",
"defaultAuthor": "Heitor Fidelis"
}
}
}
52 changes: 26 additions & 26 deletions src/services/post/files/django-optimizations.en-us.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
# Ways to optimize queries in Django 🐍🚀
## Ways to optimize queries in Django 🐍🚀

We can make our operations more performant using Django's own methods, generally request delays are consequence from multiple JOINS performed inside queries, result from model's relationships.

## 1. Using `prefetch_related()` and `select_related()`
### 1. Using `prefetch_related()` and `select_related()`

When we define the ***queryset*** of a ***view*** we can perform ***JOINS*** in advance within it. Thus, we reduce the number of operations that will be realized later.

**Example:** Within the ***serializer*** used by ***view*** we need data from some entity related to the model, to fill in a field for example. So for each instance that will be serialized, a set of operations will be performed to bring this data. When performing these operations in ***view*** when defining the ***queryset***, all operations will be done in a single shot, carrying all needed data to serializer.

### `select_related()`: Used for 1-to-1 `OneToOneField` or `ForeignKey` relationships.
**`select_related()`**: Used for 1-to-1 `OneToOneField` or `ForeignKey` relationships.

### `prefetch_related()`: Using for relationships where we will have several objects, such as `ManyToManyField` or reverse `ForeignKey` accesses.
**`prefetch_related()`**: Using for relationships where we will have several objects, such as `ManyToManyField` or reverse `ForeignKey` accesses.

### Example:
**Example:**

```python
# models.py
Expand All @@ -28,7 +28,7 @@ class Employee(models.Model):
company = models.ForeignKey(Company, on_delete=models.PROTECT, blank=True, null=True)
```

### In the `Employee` entity serializer we look for the *name* of `Company` through the *FK*, each time this *serializer* receives an instance to *serialize*, it will do a *JOIN* with ` Company` to fetch the data.
In the `Employee` entity serializer we look for the *name* of `Company` through the *FK*, each time this *serializer* receives an instance to *serialize*, it will do a *JOIN* with ` Company` to fetch the data.

```python
# serializers.py
Expand All @@ -45,7 +45,7 @@ class EmployeeSerializer(serializers.ModelSerializer):
]
```

### In the `Employee` entity *view* we use `select_related()` passing the *FK* field to `Company`, thus an *INNER JOIN* is performed in the *queryset*, without the need to be performed individually in the serializer.
In the `Employee` entity *view* we use `select_related()` passing the *FK* field to `Company`, thus an *INNER JOIN* is performed in the *queryset*, without the need to be performed individually in the serializer.

```python
# views.py
Expand All @@ -54,15 +54,15 @@ class EmployeeViewSet(ModelViewSet):
queryset = Employee.objects.select_related('company').order_by('pk')
```

### With `prefetch_related()` we can do this when we have bigger relationships.
With `prefetch_related()` we can do this when we have bigger relationships.

**In this case, `employee_set` (or the label defined in FK `related_name`) was passed as a parameter, listing the `Employees` of each `Company`.**
In this case, `employee_set` (or the label defined in FK `related_name`) was passed as a parameter, listing the `Employees` of each `Company`.

```python
queryset = Company.objects.prefetch_related('employee_set').order_by('pk')
```

### Practical Example:
**Practical Example:**

```python
queryset = Order.objects.select_related(
Expand All @@ -78,17 +78,17 @@ queryset = Order.objects.select_related(
.order_by('pk')
```

**In the `Order` entity we are performing the *JOIN* with its foreign keys `['contract', 'interest', 'company', 'owner']`, and a `prefetch_related()` with several instances accessed through the `'__'` lookups of Django fields.**
In the `Order` entity we are performing the *JOIN* with its foreign keys `['contract', 'interest', 'company', 'owner']`, and a `prefetch_related()` with several instances accessed through the `'__'` lookups of Django fields.

## 2. Avoiding loops and using methods like `aggregate()` and `update()`
### 2. Avoiding loops and using methods like `aggregate()` and `update()`

We can avoid building loops using some alternatives, depending on the context.

### `aggregate()`
**`aggregate()`**

**Inserts a field into the *queryset* and finally returns a dictionary `(dict)`.**
Inserts a field into the *queryset* and finally returns a dictionary `(dict)`.

### Example:
**Example:**

- Using `loop`

Expand All @@ -110,9 +110,9 @@ We can avoid building loops using some alternatives, depending on the context.
total_price = items.get('total_price', 0)
```

### Both ways are iterating over the objects from Item entity and adding their price field, however using `aggregate` we are performing a more performant operation due to several Django reasons and also database optimizations.
Both ways are iterating over the objects from Item entity and adding their price field, however using `aggregate` we are performing a more performant operation due to several Django reasons and also database optimizations.

### Practical Example:
**Practical Example:**

```python
# serializers.py
Expand All @@ -132,13 +132,13 @@ def get_contract_price(self, obj):
return price
```

**Here we are filtering a set of objects, then we are aggregating in the new field `total_price` the values ​from `price` field that is present in the primary key object of the `item` field. We perform aggregation with the `Sum()` operator and the `F()` operator, `F()` converts a field to be used in operations.**
Here we are filtering a set of objects, then we are aggregating in the new field `total_price` the values ​from `price` field that is present in the primary key object of the `item` field. We perform aggregation with the `Sum()` operator and the `F()` operator, `F()` converts a field to be used in operations.

### `update()`
**`update()`**

### In the same way that `aggregate` is more performant than loops, making some changes in objects using `update()` becomes more performant than changing directly from object's fields.
In the same way that `aggregate` is more performant than loops, making some changes in objects using `update()` becomes more performant than changing directly from object's fields.

### Example:
**Example:**

- Accessing fields

Expand Down Expand Up @@ -168,13 +168,13 @@ items.filter(pk__in=[15, 16, 17]).update(name='Teste')
items.filter(category='technology').update(category='tech')
```

### Both ways are updating the item's `name` field with `pk=15`, but the second becomes more performant for bulk updates or when we don't need to directly access the field. The first mode is more necessary when we need to perform some calc or logic.
Both ways are updating the item's `name` field with `pk=15`, but the second becomes more performant for bulk updates or when we don't need to directly access the field. The first mode is more necessary when we need to perform some calc or logic.

## 3. Creating a `serializer` for each specific context
### 3. Creating a `serializer` for each specific context

**If a `view` will not use all the fields from a model or you need to *serialize* an object within another `serializer`, and these fields require some effort to be *serialized*, it is worth creating a `serializer ` model-specific ` view `, using only what you will need.**
If a `view` will not use all the fields from a model or you need to *serialize* an object within another `serializer`, and these fields require some effort to be *serialized*, it is worth creating a `serializer ` model-specific ` view `, using only what you will need.

### Example:
**Example:**

```python
class ProductSerializer(serializers.ModelSerializer):
Expand Down Expand Up @@ -223,4 +223,4 @@ class ComplexProductSerializer(serializers.ModelSerializer):
]
```

### `Product` contains several serializers with clearly defined objectives, it is noticeable that the last `(ComplexProductSerializer)` generates a high volume of data, making it less performant, so in a situation where I only need the basics, I can use an existing one or create a new one with the necessary fields.
`Product` contains several serializers with clearly defined objectives, it is noticeable that the last `(ComplexProductSerializer)` generates a high volume of data, making it less performant, so in a situation where I only need the basics, I can use an existing one or create a new one with the necessary fields.
Loading

0 comments on commit 0dfbb5f

Please sign in to comment.