Updating blog post filenames and publishing very old post

This commit is contained in:
Renne Rocha 2023-08-07 20:47:39 -03:00
parent 044c31e747
commit 8e7ed8c836
9 changed files with 291 additions and 6 deletions

View file

@ -7,10 +7,8 @@ googleAnalytics: "UA-22087729-1"
params:
author: "Renne Rocha"
siteName: "Hugo Tania is Amazing"
siteDesc: "Hugo is Absurdly Fast!"
siteName: "Sharing what I learn about software development mainly"
siteDesc: "Sharing what I learn about software development mainly"
colorScheme:
toggle: true
@ -43,7 +41,7 @@ params:
menu:
header:
- name: Postagens
- name: Articles
url: "/articles/"
footer:
- name: RSS

View file

@ -0,0 +1,45 @@
---
title: "Iniciando o Internet Explorer a partir do PowerBuilder"
publishdate: 2007-09-21
tags: ["powerbuilder"]
slug: iniciando-ie-com-powerbuilder
---
Esta semana tive que iniciar um projeto em que a principal funcionalidade seria executar a partir de um botão em uma window o Internet Explorer na máquina do cliente, abrindo uma determinada URL. Pensei em usar inicialmente a função `Run()`, porém uma das limitações do projeto era que a janela do navegador não poderia ter nenhuma barra de ferramentas disponível (endereço, status, favoritos, etc)
Como não é possível iniciar o IE em linha de comando com parâmetros para ocultar essas barras de ferramentas tive que procurar outra solução. Pesquisando dentro da empresa, me sugeriram utilizar um objeto OLE para fazer essa tarefa.
Pesquisando no site do MSDN, descobri o objeto [InternetExplorer](https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa752084(v=vs.85)?redirectedfrom=MSDN) que permite trabalhar com uma instância do IE. Você pode configurar diversas propriedades desse objeto (como exibição das barras de ferramentas, tamanho da janela, etc).
Bom, no final fiz o seguinte código (utilizei o PowerBuilder 7) dentro do evento `clicked()` de um botão:
```
OLEObject uo_ie
uo_ie = CREATE OLEObject
Integer ii_handleoleobject = -999
ii_handleoleobject = uo_ie.ConnectToNewObject("InternetExplorer.Application")
IF ii_handleoleobject < 0 THEN
DESTROY uo_ie
MessageBox('Erro','Não foi ´possível criar o objeto OLE')
ELSE
uo_ie.AddressBar = FALSE
uo_ie.MenuBar = FALSE
uo_ie.Resizable = FALSE
uo_ie.StatusBar = FALSE
uo_ie.ToolBar = FALSE
uo_ie.Visible = TRUE
uo_ie.Left = 200
uo_ie.Top = 200
uo_ie.Height = 500
uo_ie.Width = 500
uo_ie.Navigate(is_urlchamada)
SetForegroundWindow(uo_ie.HWND)
END IF
```
Declarando uma função externa (para que a janela recém-criada fique ativada):
```
FUNCTION boolean SetForegroundWindow( long hWnd ) LIBRARY "USER32"
```

View file

@ -2,6 +2,7 @@
title: "Validando dados extraídos com Scrapy"
publishdate: 2019-03-08
tags: ["scrapy", "scraping", "monitoramento"]
slug: validando-dados-extraidos-com-scrapy
---
Como você garante a qualidade e a confiabilidade dos dados que você está

View file

@ -2,6 +2,7 @@
title: "Monitorando seus projetos de raspagem de dados"
publishdate: 2022-01-13
tags: ["monitoramento", "scrapy", "raspagem de dados", "python", "spidermon"]
slug: monitorando-seus-projetos-de-raspagem-de-dados
---
Quando passamos a extrair dados de uma página com regularidade, com

View file

@ -2,6 +2,7 @@
title: "Revisão de Código: Extraindo dados do site 'Aos Fatos'"
publishdate: 2022-04-08
tags: ["revisão de código", "scrapy", "raspagem de dados", "python", "live"]
slug: revisao-de-codigo-extraindo-dados-do-site-aos-fatos
---
Algumas semanas atrás, fiz a revisão de um código para extrair informações de

View file

@ -2,6 +2,7 @@
title: "Testando múltiplas chamadas de uma função com mocks"
publishdate: 2022-11-07
tags: ["python", "testes", "pytest"]
slug: testando-multiplas-chamadas-de-um-mock
---
Em algumas situações durante o teste e alguma função, queremos confirmar

View file

@ -2,6 +2,7 @@
title: "Sobre perguntas muito vagas em grupos de discussão"
publishdate: 2022-11-11
tags: ["perguntas"]
slug: sobre-perguntas-muito-vagas
---
Eu acompanho diversos grupos de tecnologia por email (hoje nem tanto),

View file

@ -2,7 +2,7 @@
title: "Extending built-in Django User with a Profile Model"
date: 2023-04-24T19:28:40-03:00
tags: ["django", "user", "python"]
draft: false
slug: extending-django-user-profile-model
---
The [user authentication](https://docs.djangoproject.com/en/4.2/topics/auth/#user-authentication-in-django) system provided by Django is extremely powerful

View file

@ -0,0 +1,237 @@
---
title: "Extending built-in Django User with a custom Model"
date: 2023-05-01T19:28:40-03:00
tags: ["django", "user", "python"]
slug: extending-django-user-with-custom-model
---
The [user authentication](https://docs.djangoproject.com/en/4.2/topics/auth/#user-authentication-in-django) system provided by Django is extremely powerful
and handles most of the authentication (Am I who I say I am?) and authorization (Am I
authorized to do what I want to do?) needs of an web project. User accounts, groups
and permissions, methods for handling passwords securely are part of this system.
Generally, this is adequate for most projects; however, there are situations where it becomes necessary to modify the behavior of a **User** or alter how their data is stored in the database. It should be noted that modifying the authorization and/or authentication process of a **User** will not be covered in this post.
Creating a user profile model is one solution to extend and modify the behavior of a **User**, as [discussed before]({{< ref "20230424-extending-django-user-profile-model" >}}), but that approach has some caveats that are solved with the use of a
custom user model.
# Custom User model
We can tell Django which is the model that will replace the built-in
`django.contrib.auth.models.User` model in the system. This is done by
providing a value to `AUTH_USER_MODEL` in your project.
{{<highlight python>}}
# myproject/myproject/settings.py
AUTH_USER_MODEL = "users.CustomUser"
{{</highlight>}}
> Usually I create a `users` application to group all custom user related
> code to keep everything in the same context
It is highly recommended that you do this configuration at the beginning
of the project, as after you have created your database tables, it will
require you to fix your schema, moving data between tables and reapplying
some migrations manually (see [#25313](https://code.djangoproject.com/ticket/25313)
for an overview of the steps involved).
Now we need to create our custom model.
This new user model can handle different authentication and authorization
schemes, can use different fields (e.g. email) to identify the user or
any other requirement that is not satisfied using the default Django user
model.
## Adding new fields to default User model
If the default **[User](https://docs.djangoproject.com/en/4.2/ref/contrib/auth/#django.contrib.auth.models.User)** model has everything we need and we want
to add some extra profile fields keeping authentication and authorization as
it is, create a custom model inheriting from `AbstractUser` would be enough.
{{<highlight python>}}
# myproject/users/models.py
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
date_of_birth = models.DateField(null=True)
{{</highlight>}}
{{<highlight python>}}
# myproject/myproject/settings.py
AUTH_USER_MODEL = "users.CustomUser"
{{</highlight>}}
As we will not create a new table to store the user related information, there is
no need for additional database queries to retrieve related models. We also don't
need to worry if a related model is created or not reducing the complexity of
the system.
## AbstractBaseUser
If we want to use a different field as the identifier (other than `email`),
use a different authorization system and/or having more control on what
fields we have in our user model, a custom model inheriting from
`AbstractBaseUser` is the choice.
`AbstractBaseUser` is the core implementation of a **User**. It has a
`password` field and methods to store and validate it securely. A
`last_login` datetime field and everything else is up to us to provide.
If using the default authentication backend, our model must have a single unique
field that will be the identifier of our user such as email address, username or
any other unique attribute.
You configure that attribute using `USERNAME_FIELD` that defines what is
the field that will uniquely identify the user.
`EMAIL_FIELD`
`REQUIRED_FIELDS`
`is_active` is an attribute on `AbstractBaseUser` defaulting to `True`
As an example, we will define a custom user that will use the email address
as the identifier, has the date of birth as one required field can store
the phone number and has a flag field in the database to indicate if the user
is active or not.
{{<highlight python>}}
# myproject/users/models.py
from django.contrib.auth.models import AbstractBaseUser
class CustomUser(AbstractBaseUser):
USERNAME_FIELD = "email"
EMAIL_FIELD = "email"
REQUIRED_FIELDS = ["date_of_birth", ]
date_of_birth = models.EmailField(unique=True)
email = models.EmailField(unique=True)
is_active = models.BooleanField(default=True)
phone_number = models.CharField(max_length=16, blank=True)
{{</highlight>}}
FROM DOCS Authentication backends provide an extensible system for when a username and password stored with the user model need to be authenticated against a different service than Djangos default.
TODO: list all fields that are created with this
Any other fields needs to be created.
is_active is a property set to True, but you can define if you want
USERNAME_FIELD is needed identifier unique = True
EMAIL_FIELD to specifi what is the email field
REQUIRED_FIELDS fields required when createsuperuser
If we want to use `email` as the identifier of an user,
we need to set `USERNAME_FIELD` property
{{<highlight python>}}
# myproject/users/models.py
class CustomUser(AbstractBaseUser):
USERNAME_FIELD = "email"
email = models.EmailField()
{{</highlight>}}
One drawback is you need to specify a Custom Manager implementing
two methods: `create_user` and `create_superuser`. This is required
so we willll be able to run `python manage.py createsuperuser`
and `python manage.py create-user`.
If some fields (TODO list what fields) from `ABstractUser` are there, you can
use the built-in UserManager
FROM DOCS username, email, is_staff, is_active, is_superuser, last_login, and date_joined fields the same as Djangos default user, you can install Djangos UserManager
{{<highlight python>}}
# myproject/users/models.py
class CustomUser(AbstractBaseUser):
USERNAME_FILED = "email"
email = models.EmailField()
objects = UserManager()
{{</highlight>}}
If you don't want to use Django Admin (very unlikely), you're done,
and you can create/manage your users and authentication backend will
be able.
However, if you want to use this custom user model with Django admin, there are
some extra steps.
We need some fields and methods:
`is_staff` so you have access to django admin
`is_active` inactive users can't access django admin
to manage permissions to edit registered models
`has_perm`
`has_module_perms()`
***we don't need to use the built-in permission system (see PermissionMixin)***
And `UserCreationForm`< `UserChangeForm` and `PasswordResetForm` (if we don't have email field)
needs to be customized so we can use that.
Also we need a custom UserAdmin to use our custom forms.
This is a lot of things, and sometimes difficult to remember. The docs
are ok to describe the process, but IMO this should be much simpler :-P
If by any chance you want to use django model permission, you can
use PermissionMixin, so you have access to groups, etc (to be honest, I
never saw anything using permission, but groups)
Sometimes the username may not be the way you want to identify an user
(an email or social number would be more suitable for your project)
or we have different requirements for authorization and permission. In
those cases creating a custom user model is a option.
This has advatanges over the user of a user profile model and solve some
of the caveats of that approach such as:
- We won't need an extra database table to store your custom fields, so
there is no performance problems to access them;
- As the table that we store the User data required for Django authentication
is the same, we don't need to bother if your profile fields will be available
or not
When creating a custom user model, we have two different options
If you are going to this path, you can create your custom user
inheriting from two different classes:
If using Django Admin, we also need to register this new model.
{{<highlight python>}}
# myproject/users/admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import CustomUser
admin.site.register(CustomUser, UserAdmin)
{{</highlight>}}