current position:Home>Elegant implementation of Django model field encryption

Elegant implementation of Django model field encryption

2022-01-30 08:09:14 Coffee bar

An earlier article Django Example of developing password management table Yes, we wrote a password management tool to manage passwords , At that time, the function of encryption and decryption was view Layer implementation , It has been running stably, so it doesn't pay too much attention to whether the implementation is elegant . Recently, we need to add a few more password tables. Looking back at the previous code, we find that the encryption and decryption is in view Layer implementation is cumbersome , Especially with Sadmin The public library after view The code is much simpler , If you stay view Layer handling is obviously not elegant , It's time to achieve... In a more elegant way

Sadmin Additions and deletions

Adding, deleting, modifying and querying database tables is the most commonly used function in the development process , The previous article also introduced us through encapsulation Sadmin The public library With the most concise code to achieve the addition, deletion, modification and query of the table , How concise is it , Look at the code below

class TableList(ListCreateView):
    model = Table
    template = 'password/table.html'
    permission = {'get': 'password.select_table', 'post': 'password.create_table'}


class TableDetail(RetrieveUpdateDestroyView):
    model = Table
    permission = {'get': 'password.select_table', 'put': 'password.update_table',
                  'delete': 'password.delete_table'}
 Copy code 

TableList Class can query tables and create new table data ,TableDetail You can query a single piece of data in the table 、 Modification and deletion , Corresponds to two URL

path('table/', views.TableList.as_view(), name='table-list-url'),
path('table/<int:pk>/', views.TableDetail.as_view(), name='table-detail-url'),
 Copy code 

If in view If the layer implements the encryption of table fields , That's going to be rewritten TableList Of post Method , as well as TableDetail Class put Method , Very trouble , So what's more elegant ? It is better to handle the table fields when the table changes , Directly in model Layer is obviously better than view More appropriate ,model If it is implemented through Django Of signals or rewrite model Of save Method All good choices

As for the use of signals Or rewrite save Method , Both can be achieved , Personally, I think rewriting is adopted for simple processing logic save It's a better way , For complex processing logic signals Clearer , For our need to encrypt fields , The logic is simple, and the code doesn't need too much , Directly adopt rewriting save Just the way

rewrite model Of save Method

For the core code of encryption and decryption, you can refer to the article Django Example of developing password management table Given the source code , rewrite model Of save The method code is as follows

class Table(models.Model):
    username = models.CharField(max_length=64, verbose_name=' user name ')
    password = models.CharField(max_length=512, verbose_name=' password ')

    def __str__(self):
        return self.application_name

    def save(self, *args, **kwargs):
        _encrypt = True

        if self.pk:
            old_password = Table.objects.get(id=self.id)
            _encrypt = False if old_password.password == self.password else True

        if _encrypt:
            _m = RsaCrypto().encrypt(self.password)
            if _m.get('state'):
                self.password = _m.get('message')
            else:
                raise Exception(' Encryption failed :' + _m.get('message'))

        super(Table, self).save(*args, **kwargs)
 Copy code 

For password encryption , Usually new records will be added for the first time , And update the record when the password changes

whenever save How to judge is insert still update Well ? It can be determined by whether there is self.pk To judge ,Django Of model There must be a field for the primary key , If the user does not set the primary key field , that Django By default, a file named id The field of is used as the primary key , The primary key is also used pk Alias to denote , So you can go through self.pk Whether it exists to judge this save Is it insert still update

When this time save by update when , We also need to determine whether the password field has changed , If there is no change, there is no need to call the encryption method , To determine whether the field changes, you need to obtain the value before the field is submitted , The value before submission can be through Table.objects.get(id=self.id) To get

With all this information , Then encryption will come naturally . We gracefully implement the field encryption , What about decryption ? Personally, I think it's the same model Libby wrote veiw It's more suitable , Can be in mdel Add a decode_password Methods

class Table(models.Model):
    ...
    
    def decode_password(self):
        _m = RsaCrypto().decrypt(self.password)
        if _m.get('state'):
            return {
                'state': 1,
                'message': _m.get('message'),
                'username': self.username
            }
        else:
            return {'state': 0, 'message': 'Error: ' + _m.get('message')}
 Copy code 

Call... When decryption is required Model Of decode_password The method is ok

def decode_password(request, pk):
    try:
        _t = Table.objects.get(id=pk)
        return JsonResponse(_t.decode_password())
    except Exception as e:
        return JsonResponse({'state': 0, 'message': 'Error: ' + str(e)})
 Copy code 

At the end

I'm a little obsessed with code , The implementation function is also simple and practical , can 2 OK, I'll never write 3 That's ok , If there is a better solution, you will not hesitate to reconstruct , At the same time, we firmly oppose “ It's not useless ” That's what I'm saying . Whether the above implementation is elegant , Or there is a better solution , Welcome to discuss

copyright notice
author[Coffee bar],Please bring the original link to reprint, thank you.
https://en.pythonmana.com/2022/01/202201300809117381.html

Random recommended